mock_redis 0.5.4 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/lint.yml +31 -0
- data/.github/workflows/tests.yml +63 -0
- data/.gitignore +1 -1
- data/.overcommit.yml +21 -0
- data/.rspec +1 -1
- data/.rubocop.yml +148 -0
- data/.rubocop_todo.yml +35 -0
- data/.simplecov +4 -0
- data/CHANGELOG.md +278 -0
- data/Gemfile +9 -5
- data/LICENSE.md +21 -0
- data/README.md +52 -16
- data/Rakefile +0 -8
- data/lib/mock_redis/assertions.rb +0 -1
- data/lib/mock_redis/connection_method.rb +13 -0
- data/lib/mock_redis/database.rb +193 -257
- data/lib/mock_redis/expire_wrapper.rb +2 -2
- data/lib/mock_redis/future.rb +23 -0
- data/lib/mock_redis/geospatial_methods.rb +240 -0
- data/lib/mock_redis/hash_methods.rb +83 -24
- data/lib/mock_redis/indifferent_hash.rb +11 -0
- data/lib/mock_redis/info_method.rb +160 -0
- data/lib/mock_redis/list_methods.rb +34 -19
- data/lib/mock_redis/multi_db_wrapper.rb +8 -7
- data/lib/mock_redis/pipelined_wrapper.rb +42 -16
- data/lib/mock_redis/set_methods.rb +62 -19
- data/lib/mock_redis/sort_method.rb +81 -0
- data/lib/mock_redis/stream/id.rb +58 -0
- data/lib/mock_redis/stream.rb +88 -0
- data/lib/mock_redis/stream_methods.rb +102 -0
- data/lib/mock_redis/string_methods.rb +235 -42
- data/lib/mock_redis/transaction_wrapper.rb +62 -28
- data/lib/mock_redis/utility_methods.rb +62 -11
- data/lib/mock_redis/version.rb +4 -1
- data/lib/mock_redis/zset.rb +24 -29
- data/lib/mock_redis/zset_methods.rb +187 -59
- data/lib/mock_redis.rb +77 -27
- data/mock_redis.gemspec +23 -15
- data/spec/client_spec.rb +29 -0
- data/spec/cloning_spec.rb +17 -18
- data/spec/commands/append_spec.rb +4 -4
- data/spec/commands/auth_spec.rb +1 -1
- data/spec/commands/bgrewriteaof_spec.rb +2 -2
- data/spec/commands/bgsave_spec.rb +2 -2
- data/spec/commands/bitcount_spec.rb +25 -0
- data/spec/commands/bitfield_spec.rb +169 -0
- data/spec/commands/blpop_spec.rb +19 -21
- data/spec/commands/brpop_spec.rb +25 -20
- data/spec/commands/brpoplpush_spec.rb +16 -17
- data/spec/commands/connected_spec.rb +7 -0
- data/spec/commands/connection_spec.rb +15 -0
- data/spec/commands/dbsize_spec.rb +3 -3
- data/spec/commands/decr_spec.rb +8 -8
- data/spec/commands/decrby_spec.rb +8 -8
- data/spec/commands/del_spec.rb +35 -3
- data/spec/commands/disconnect_spec.rb +7 -0
- data/spec/commands/dump_spec.rb +19 -0
- data/spec/commands/echo_spec.rb +4 -4
- data/spec/commands/eval_spec.rb +7 -0
- data/spec/commands/evalsha_spec.rb +10 -0
- data/spec/commands/exists_spec.rb +36 -7
- data/spec/commands/expire_spec.rb +48 -20
- data/spec/commands/expireat_spec.rb +12 -13
- data/spec/commands/flushall_spec.rb +5 -5
- data/spec/commands/flushdb_spec.rb +5 -5
- data/spec/commands/future_spec.rb +30 -0
- data/spec/commands/geoadd_spec.rb +58 -0
- data/spec/commands/geodist_spec.rb +118 -0
- data/spec/commands/geohash_spec.rb +52 -0
- data/spec/commands/geopos_spec.rb +55 -0
- data/spec/commands/get_spec.rb +14 -6
- data/spec/commands/getbit_spec.rb +7 -7
- data/spec/commands/getrange_spec.rb +9 -9
- data/spec/commands/getset_spec.rb +7 -7
- data/spec/commands/hdel_spec.rb +41 -11
- data/spec/commands/hexists_spec.rb +11 -11
- data/spec/commands/hget_spec.rb +7 -7
- data/spec/commands/hgetall_spec.rb +15 -5
- data/spec/commands/hincrby_spec.rb +16 -16
- data/spec/commands/hincrbyfloat_spec.rb +58 -0
- data/spec/commands/hkeys_spec.rb +5 -5
- data/spec/commands/hlen_spec.rb +5 -5
- data/spec/commands/hmget_spec.rb +19 -9
- data/spec/commands/hmset_spec.rb +38 -12
- data/spec/commands/hscan_each_spec.rb +48 -0
- data/spec/commands/hscan_spec.rb +27 -0
- data/spec/commands/hset_spec.rb +26 -12
- data/spec/commands/hsetnx_spec.rb +16 -16
- data/spec/commands/hvals_spec.rb +5 -5
- data/spec/commands/incr_spec.rb +8 -8
- data/spec/commands/incrby_spec.rb +13 -13
- data/spec/commands/incrbyfloat_spec.rb +13 -13
- data/spec/commands/info_spec.rb +54 -5
- data/spec/commands/keys_spec.rb +83 -31
- data/spec/commands/lastsave_spec.rb +2 -2
- data/spec/commands/lindex_spec.rb +20 -10
- data/spec/commands/linsert_spec.rb +14 -14
- data/spec/commands/llen_spec.rb +4 -4
- data/spec/commands/lpop_spec.rb +6 -6
- data/spec/commands/lpush_spec.rb +21 -15
- data/spec/commands/lpushx_spec.rb +24 -11
- data/spec/commands/lrange_spec.rb +24 -8
- data/spec/commands/lrem_spec.rb +16 -16
- data/spec/commands/lset_spec.rb +17 -12
- data/spec/commands/ltrim_spec.rb +17 -7
- data/spec/commands/mapped_hmget_spec.rb +13 -9
- data/spec/commands/mapped_hmset_spec.rb +12 -12
- data/spec/commands/mapped_mget_spec.rb +22 -0
- data/spec/commands/mapped_mset_spec.rb +19 -0
- data/spec/commands/mapped_msetnx_spec.rb +26 -0
- data/spec/commands/mget_spec.rb +48 -17
- data/spec/commands/move_spec.rb +37 -37
- data/spec/commands/mset_spec.rb +20 -6
- data/spec/commands/msetnx_spec.rb +14 -14
- data/spec/commands/persist_spec.rb +15 -16
- data/spec/commands/pexpire_spec.rb +86 -0
- data/spec/commands/pexpireat_spec.rb +48 -0
- data/spec/commands/ping_spec.rb +6 -2
- data/spec/commands/pipelined_spec.rb +98 -7
- data/spec/commands/pttl_spec.rb +41 -0
- data/spec/commands/randomkey_spec.rb +3 -3
- data/spec/commands/rename_spec.rb +16 -12
- data/spec/commands/renamenx_spec.rb +13 -15
- data/spec/commands/restore_spec.rb +47 -0
- data/spec/commands/rpop_spec.rb +6 -6
- data/spec/commands/rpoplpush_spec.rb +13 -8
- data/spec/commands/rpush_spec.rb +21 -15
- data/spec/commands/rpushx_spec.rb +24 -11
- data/spec/commands/sadd_spec.rb +14 -10
- data/spec/commands/scan_each_spec.rb +39 -0
- data/spec/commands/scan_spec.rb +64 -0
- data/spec/commands/scard_spec.rb +3 -3
- data/spec/commands/script_spec.rb +9 -0
- data/spec/commands/sdiff_spec.rb +13 -13
- data/spec/commands/sdiffstore_spec.rb +13 -13
- data/spec/commands/select_spec.rb +13 -5
- data/spec/commands/set_spec.rb +112 -0
- data/spec/commands/setbit_spec.rb +25 -16
- data/spec/commands/setex_spec.rb +20 -4
- data/spec/commands/setnx_spec.rb +6 -6
- data/spec/commands/setrange_spec.rb +12 -12
- data/spec/commands/sinter_spec.rb +11 -13
- data/spec/commands/sinterstore_spec.rb +12 -12
- data/spec/commands/sismember_spec.rb +10 -10
- data/spec/commands/smembers_spec.rb +15 -5
- data/spec/commands/smove_spec.rb +13 -13
- data/spec/commands/sort_list_spec.rb +21 -0
- data/spec/commands/sort_set_spec.rb +21 -0
- data/spec/commands/sort_zset_spec.rb +21 -0
- data/spec/commands/spop_spec.rb +19 -4
- data/spec/commands/srandmember_spec.rb +28 -4
- data/spec/commands/srem_spec.rb +17 -12
- data/spec/commands/sscan_each_spec.rb +48 -0
- data/spec/commands/sscan_spec.rb +39 -0
- data/spec/commands/strlen_spec.rb +4 -5
- data/spec/commands/sunion_spec.rb +13 -11
- data/spec/commands/sunionstore_spec.rb +12 -12
- data/spec/commands/ttl_spec.rb +11 -6
- data/spec/commands/type_spec.rb +1 -1
- data/spec/commands/watch_spec.rb +9 -4
- data/spec/commands/xadd_spec.rb +122 -0
- data/spec/commands/xlen_spec.rb +22 -0
- data/spec/commands/xrange_spec.rb +164 -0
- data/spec/commands/xread_spec.rb +66 -0
- data/spec/commands/xrevrange_spec.rb +130 -0
- data/spec/commands/xtrim_spec.rb +36 -0
- data/spec/commands/zadd_spec.rb +100 -11
- data/spec/commands/zcard_spec.rb +4 -4
- data/spec/commands/zcount_spec.rb +18 -10
- data/spec/commands/zincrby_spec.rb +6 -6
- data/spec/commands/zinterstore_spec.rb +54 -20
- data/spec/commands/zpopmax_spec.rb +60 -0
- data/spec/commands/zpopmin_spec.rb +60 -0
- data/spec/commands/zrange_spec.rb +54 -13
- data/spec/commands/zrangebyscore_spec.rb +42 -27
- data/spec/commands/zrank_spec.rb +4 -4
- data/spec/commands/zrem_spec.rb +18 -12
- data/spec/commands/zremrangebyrank_spec.rb +5 -5
- data/spec/commands/zremrangebyscore_spec.rb +12 -5
- data/spec/commands/zrevrange_spec.rb +35 -10
- data/spec/commands/zrevrangebyscore_spec.rb +26 -15
- data/spec/commands/zrevrank_spec.rb +4 -4
- data/spec/commands/zscan_each_spec.rb +48 -0
- data/spec/commands/zscan_spec.rb +26 -0
- data/spec/commands/zscore_spec.rb +7 -7
- data/spec/commands/zunionstore_spec.rb +54 -21
- data/spec/mock_redis_spec.rb +61 -0
- data/spec/spec_helper.rb +35 -8
- data/spec/support/redis_multiplexer.rb +62 -37
- data/spec/support/shared_examples/does_not_cleanup_empty_strings.rb +14 -0
- data/spec/support/shared_examples/only_operates_on_hashes.rb +5 -3
- data/spec/support/shared_examples/only_operates_on_lists.rb +5 -3
- data/spec/support/shared_examples/only_operates_on_sets.rb +5 -3
- data/spec/support/shared_examples/only_operates_on_strings.rb +4 -4
- data/spec/support/shared_examples/only_operates_on_zsets.rb +18 -16
- data/spec/support/shared_examples/sorts_enumerables.rb +56 -0
- data/spec/transactions_spec.rb +79 -29
- metadata +162 -42
- data/LICENSE +0 -19
- data/spec/commands/hash_operator_spec.rb +0 -21
data/lib/mock_redis.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'set'
|
2
|
+
require 'ruby2_keywords'
|
2
3
|
|
3
4
|
require 'mock_redis/assertions'
|
4
5
|
require 'mock_redis/database'
|
5
6
|
require 'mock_redis/expire_wrapper'
|
7
|
+
require 'mock_redis/future'
|
6
8
|
require 'mock_redis/multi_db_wrapper'
|
7
9
|
require 'mock_redis/pipelined_wrapper'
|
8
10
|
require 'mock_redis/transaction_wrapper'
|
@@ -14,14 +16,16 @@ class MockRedis
|
|
14
16
|
attr_reader :options
|
15
17
|
|
16
18
|
DEFAULTS = {
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
:scheme => 'redis',
|
20
|
+
:host => '127.0.0.1',
|
21
|
+
:port => 6379,
|
22
|
+
:path => nil,
|
23
|
+
:timeout => 5.0,
|
24
|
+
:password => nil,
|
25
|
+
:logger => nil,
|
26
|
+
:db => 0,
|
27
|
+
:time_class => Time,
|
28
|
+
}.freeze
|
25
29
|
|
26
30
|
def self.connect(*args)
|
27
31
|
new(*args)
|
@@ -34,40 +38,62 @@ class MockRedis
|
|
34
38
|
TransactionWrapper.new(
|
35
39
|
ExpireWrapper.new(
|
36
40
|
MultiDbWrapper.new(
|
37
|
-
|
41
|
+
Database.new(self, *args)
|
42
|
+
)
|
43
|
+
)
|
44
|
+
)
|
45
|
+
)
|
38
46
|
end
|
39
47
|
|
40
48
|
def id
|
41
|
-
"redis://#{
|
49
|
+
"redis://#{host}:#{port}/#{db}"
|
42
50
|
end
|
43
|
-
alias
|
51
|
+
alias location id
|
44
52
|
|
45
|
-
def call(command, &
|
46
|
-
|
53
|
+
def call(command, &_block)
|
54
|
+
send(*command)
|
47
55
|
end
|
48
56
|
|
49
57
|
def host
|
50
|
-
|
58
|
+
options[:host]
|
51
59
|
end
|
52
60
|
|
53
61
|
def port
|
54
|
-
|
62
|
+
options[:port]
|
55
63
|
end
|
56
64
|
|
57
65
|
def db
|
58
|
-
|
66
|
+
options[:db]
|
67
|
+
end
|
68
|
+
|
69
|
+
def logger
|
70
|
+
options[:logger]
|
71
|
+
end
|
72
|
+
|
73
|
+
def time_at(timestamp)
|
74
|
+
options[:time_class].at(timestamp)
|
59
75
|
end
|
60
76
|
|
61
77
|
def client
|
62
78
|
self
|
63
79
|
end
|
64
80
|
|
65
|
-
def
|
81
|
+
def connect
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
def reconnect
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
def respond_to?(method, include_private = false)
|
66
90
|
super || @db.respond_to?(method, include_private)
|
67
91
|
end
|
68
92
|
|
69
|
-
def method_missing(method, *args, &block)
|
70
|
-
|
93
|
+
ruby2_keywords def method_missing(method, *args, &block)
|
94
|
+
logging([[method, *args]]) do
|
95
|
+
@db.send(method, *args, &block)
|
96
|
+
end
|
71
97
|
end
|
72
98
|
|
73
99
|
def initialize_copy(source)
|
@@ -75,27 +101,26 @@ class MockRedis
|
|
75
101
|
@db = @db.clone
|
76
102
|
end
|
77
103
|
|
78
|
-
|
79
104
|
protected
|
80
105
|
|
81
106
|
def _parse_options(options)
|
82
|
-
return
|
107
|
+
return DEFAULTS.dup if options.nil?
|
83
108
|
|
84
109
|
defaults = DEFAULTS.dup
|
85
110
|
|
86
|
-
url = options[:url] || ENV[
|
111
|
+
url = options[:url] || ENV['REDIS_URL']
|
87
112
|
|
88
113
|
# Override defaults from URL if given
|
89
114
|
if url
|
90
|
-
require
|
115
|
+
require 'uri'
|
91
116
|
|
92
117
|
uri = URI(url)
|
93
118
|
|
94
|
-
if uri.scheme ==
|
95
|
-
defaults[:path]
|
119
|
+
if uri.scheme == 'unix'
|
120
|
+
defaults[:path] = uri.path
|
96
121
|
else
|
97
122
|
# Require the URL to have at least a host
|
98
|
-
raise ArgumentError,
|
123
|
+
raise ArgumentError, 'invalid url' unless uri.host
|
99
124
|
|
100
125
|
defaults[:scheme] = uri.scheme
|
101
126
|
defaults[:host] = uri.host
|
@@ -108,7 +133,7 @@ class MockRedis
|
|
108
133
|
options = defaults.merge(options)
|
109
134
|
|
110
135
|
if options[:path]
|
111
|
-
options[:scheme] =
|
136
|
+
options[:scheme] = 'unix'
|
112
137
|
options.delete(:host)
|
113
138
|
options.delete(:port)
|
114
139
|
else
|
@@ -122,4 +147,29 @@ class MockRedis
|
|
122
147
|
options
|
123
148
|
end
|
124
149
|
|
150
|
+
def logging(commands)
|
151
|
+
return yield unless logger&.debug?
|
152
|
+
|
153
|
+
begin
|
154
|
+
commands.each do |name, *args|
|
155
|
+
logged_args = args.map do |a|
|
156
|
+
if a.respond_to?(:inspect) then a.inspect
|
157
|
+
elsif a.respond_to?(:to_s) then a.to_s
|
158
|
+
else
|
159
|
+
# handle poorly-behaved descendants of BasicObject
|
160
|
+
klass = a.instance_exec { (class << self; self end).superclass }
|
161
|
+
"\#<#{klass}:#{a.__id__}>"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
logger.debug("[MockRedis] command=#{name.to_s.upcase} args=#{logged_args.join(' ')}")
|
165
|
+
end
|
166
|
+
|
167
|
+
t1 = Time.now
|
168
|
+
yield
|
169
|
+
ensure
|
170
|
+
if t1
|
171
|
+
logger.debug(format('[MockRedis] call_time=%<time>0.2f ms', time: ((Time.now - t1) * 1000)))
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
125
175
|
end
|
data/mock_redis.gemspec
CHANGED
@@ -1,24 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require "mock_redis/version"
|
1
|
+
$LOAD_PATH << File.expand_path('lib', __dir__)
|
2
|
+
require 'mock_redis/version'
|
4
3
|
|
5
4
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
5
|
+
s.name = 'mock_redis'
|
7
6
|
s.version = MockRedis::VERSION
|
7
|
+
s.license = 'MIT'
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = ['
|
10
|
-
s.email = ['
|
11
|
-
s.homepage =
|
12
|
-
s.summary =
|
9
|
+
s.authors = ['Shane da Silva', 'Samuel Merritt']
|
10
|
+
s.email = ['shane@dasilva.io']
|
11
|
+
s.homepage = 'https://github.com/sds/mock_redis'
|
12
|
+
s.summary = 'Redis mock that just lives in memory; useful for testing.'
|
13
13
|
|
14
|
-
s.description =
|
14
|
+
s.description = <<-MSG.strip.gsub(/\s+/, ' ')
|
15
|
+
Instantiate one with `redis = MockRedis.new` and treat it like you would a
|
16
|
+
normal Redis object. It supports all the usual Redis operations.
|
17
|
+
MSG
|
15
18
|
|
16
19
|
s.files = `git ls-files`.split("\n")
|
17
|
-
s.test_files = `git ls-files --
|
18
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
-
s.require_paths = [
|
20
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
22
|
+
s.require_paths = ['lib']
|
20
23
|
|
21
|
-
s.
|
22
|
-
|
23
|
-
s.
|
24
|
+
s.required_ruby_version = '>= 2.4'
|
25
|
+
|
26
|
+
s.add_runtime_dependency 'ruby2_keywords'
|
27
|
+
|
28
|
+
s.add_development_dependency 'redis', '~> 4.2.0'
|
29
|
+
s.add_development_dependency 'rspec', '~> 3.0'
|
30
|
+
s.add_development_dependency 'rspec-its', '~> 1.0'
|
31
|
+
s.add_development_dependency 'timecop', '~> 0.9.1'
|
24
32
|
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'client' do
|
4
|
+
context '#reconnect' do
|
5
|
+
it 'reconnects' do
|
6
|
+
redis = MockRedis.new
|
7
|
+
redis.reconnect.should == redis
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context '#connect' do
|
12
|
+
it 'connects' do
|
13
|
+
redis = MockRedis.new
|
14
|
+
redis.connect.should == redis
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context '#disconnect!' do
|
19
|
+
it 'responds to disconnect!' do
|
20
|
+
expect(MockRedis.new).to respond_to(:disconnect!)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context '#close' do
|
25
|
+
it 'responds to close' do
|
26
|
+
expect(MockRedis.new).to respond_to(:close)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/cloning_spec.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe 'MockRedis#clone' do
|
4
4
|
before do
|
5
5
|
@mock = MockRedis.new
|
6
6
|
end
|
7
7
|
|
8
|
-
context
|
8
|
+
context 'the stored data' do
|
9
9
|
before do
|
10
10
|
@mock.set('foo', 'bar')
|
11
11
|
@mock.hset('foohash', 'bar', 'baz')
|
@@ -16,60 +16,60 @@ describe "MockRedis#clone" do
|
|
16
16
|
@clone = @mock.clone
|
17
17
|
end
|
18
18
|
|
19
|
-
it
|
19
|
+
it 'copies the stored data to the clone' do
|
20
20
|
@clone.get('foo').should == 'bar'
|
21
21
|
end
|
22
22
|
|
23
|
-
it
|
23
|
+
it 'performs a deep copy (string values)' do
|
24
24
|
@mock.del('foo')
|
25
25
|
@clone.get('foo').should == 'bar'
|
26
26
|
end
|
27
27
|
|
28
|
-
it
|
28
|
+
it 'performs a deep copy (list values)' do
|
29
29
|
@mock.lpop('foolist')
|
30
30
|
@clone.lrange('foolist', 0, 1).should == ['bar']
|
31
31
|
end
|
32
32
|
|
33
|
-
it
|
33
|
+
it 'performs a deep copy (hash values)' do
|
34
34
|
@mock.hset('foohash', 'bar', 'quux')
|
35
|
-
@clone.hgetall('foohash').should == {'bar' => 'baz'}
|
35
|
+
@clone.hgetall('foohash').should == { 'bar' => 'baz' }
|
36
36
|
end
|
37
37
|
|
38
|
-
it
|
38
|
+
it 'performs a deep copy (set values)' do
|
39
39
|
@mock.srem('fooset', 'bar')
|
40
40
|
@clone.smembers('fooset').should == ['bar']
|
41
41
|
end
|
42
42
|
|
43
|
-
it
|
43
|
+
it 'performs a deep copy (zset values)' do
|
44
44
|
@mock.zadd('foozset', 2, 'bar')
|
45
45
|
@clone.zscore('foozset', 'bar').should == 1.0
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
context
|
49
|
+
context 'expiration times' do
|
50
50
|
before do
|
51
51
|
@mock.set('foo', 1)
|
52
|
-
@mock.expire('foo',
|
52
|
+
@mock.expire('foo', 60_026)
|
53
53
|
|
54
54
|
@clone = @mock.clone
|
55
55
|
end
|
56
56
|
|
57
|
-
it
|
57
|
+
it 'copies the expiration times' do
|
58
58
|
@clone.ttl('foo').should > 0
|
59
59
|
end
|
60
60
|
|
61
|
-
it
|
61
|
+
it 'deep-copies the expiration times' do
|
62
62
|
@mock.persist('foo')
|
63
63
|
@clone.ttl('foo').should > 0
|
64
64
|
end
|
65
65
|
|
66
|
-
it
|
66
|
+
it 'deep-copies the expiration times' do
|
67
67
|
@clone.persist('foo')
|
68
68
|
@mock.ttl('foo').should > 0
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
context
|
72
|
+
context 'transactional info' do
|
73
73
|
before do
|
74
74
|
@mock.multi
|
75
75
|
@mock.incr('foo')
|
@@ -79,18 +79,17 @@ describe "MockRedis#clone" do
|
|
79
79
|
@clone = @mock.clone
|
80
80
|
end
|
81
81
|
|
82
|
-
it
|
82
|
+
it 'makes sure the clone is in a transaction' do
|
83
83
|
lambda do
|
84
84
|
@clone.exec
|
85
85
|
end.should_not raise_error
|
86
86
|
end
|
87
87
|
|
88
|
-
it
|
88
|
+
it 'deep-copies the queued commands' do
|
89
89
|
@clone.incrby('foo', 8)
|
90
90
|
@clone.exec.should == [1, 3, 7, 15]
|
91
91
|
|
92
92
|
@mock.exec.should == [1, 3, 7]
|
93
93
|
end
|
94
94
|
end
|
95
|
-
|
96
95
|
end
|
@@ -3,22 +3,22 @@ require 'spec_helper'
|
|
3
3
|
describe '#append(key, value)' do
|
4
4
|
before { @key = 'mock-redis-test:append' }
|
5
5
|
|
6
|
-
it
|
6
|
+
it 'returns the new length of the string' do
|
7
7
|
@redises.set(@key, 'porkchop')
|
8
8
|
@redises.append(@key, 'sandwiches').should == 18
|
9
9
|
end
|
10
10
|
|
11
|
-
it
|
11
|
+
it 'appends value to the previously-stored value' do
|
12
12
|
@redises.set(@key, 'porkchop')
|
13
13
|
@redises.append(@key, 'sandwiches')
|
14
14
|
|
15
15
|
@redises.get(@key).should == 'porkchopsandwiches'
|
16
16
|
end
|
17
17
|
|
18
|
-
it
|
18
|
+
it 'treats a missing key as an empty string' do
|
19
19
|
@redises.append(@key, 'foo')
|
20
20
|
@redises.get(@key).should == 'foo'
|
21
21
|
end
|
22
22
|
|
23
|
-
it_should_behave_like
|
23
|
+
it_should_behave_like 'a string-only command'
|
24
24
|
end
|
data/spec/commands/auth_spec.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#bitcount(key [, start, end ])' do
|
4
|
+
before do
|
5
|
+
@key = 'mock-redis-test:bitcount'
|
6
|
+
@redises.set(@key, 'foobar')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'gets the number of set bits from the key' do
|
10
|
+
@redises.bitcount(@key).should == 26
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'gets the number of set bits from the key in an interval' do
|
14
|
+
@redises.bitcount(@key, 0, 1000).should == 26
|
15
|
+
@redises.bitcount(@key, 0, 0).should == 4
|
16
|
+
@redises.bitcount(@key, 1, 1).should == 6
|
17
|
+
@redises.bitcount(@key, 1, -2).should == 18
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'treats nonexistent keys as empty strings' do
|
21
|
+
@redises.bitcount('mock-redis-test:not-found').should == 0
|
22
|
+
end
|
23
|
+
|
24
|
+
it_should_behave_like 'a string-only command'
|
25
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#bitfield(*args)' do
|
4
|
+
before :each do
|
5
|
+
@key = 'mock-redis-test:bitfield'
|
6
|
+
@redises.set(@key, '')
|
7
|
+
|
8
|
+
@redises.bitfield(@key, :set, 'i8', 0, 78)
|
9
|
+
@redises.bitfield(@key, :set, 'i8', 8, 104)
|
10
|
+
@redises.bitfield(@key, :set, 'i8', 16, -59)
|
11
|
+
@redises.bitfield(@key, :set, 'u8', 24, 78)
|
12
|
+
@redises.bitfield(@key, :set, 'u8', 32, 84)
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with a :get command' do
|
16
|
+
it 'gets a signed 8 bit value' do
|
17
|
+
@redises.bitfield(@key, :get, 'i8', 0).should == [78]
|
18
|
+
@redises.bitfield(@key, :get, 'i8', 8).should == [104]
|
19
|
+
@redises.bitfield(@key, :get, 'i8', 16).should == [-59]
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'gets multiple values with multiple command args' do
|
23
|
+
@redises.bitfield(@key, :get, 'i8', 0,
|
24
|
+
:get, 'i8', 8,
|
25
|
+
:get, 'i8', 16).should == [78, 104, -59]
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'gets multiple values using positional offsets' do
|
29
|
+
@redises.bitfield(@key, :get, 'i8', '#0',
|
30
|
+
:get, 'i8', '#1',
|
31
|
+
:get, 'i8', '#2').should == [78, 104, -59]
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'shows an error with an invalid type' do
|
35
|
+
expect do
|
36
|
+
@redises.bitfield(@key, :get, 'u64', 0)
|
37
|
+
end.to raise_error(Redis::CommandError)
|
38
|
+
expect do
|
39
|
+
@redises.bitfield(@key, :get, 'i128', 0)
|
40
|
+
end.to raise_error(Redis::CommandError)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'does not throw an error with i64 type' do
|
44
|
+
expect do
|
45
|
+
@redises.bitfield(@key, :get, 'i64', 0)
|
46
|
+
end.to_not raise_error
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'with a :set command' do
|
51
|
+
it 'sets the bit values for an 8 bit signed integer' do
|
52
|
+
@redises.bitfield(@key, :set, 'i8', 0, 63).should == [78]
|
53
|
+
@redises.bitfield(@key, :set, 'i8', 8, -1).should == [104]
|
54
|
+
@redises.bitfield(@key, :set, 'i8', 16, 123).should == [-59]
|
55
|
+
|
56
|
+
@redises.bitfield(@key, :get, 'i8', 0,
|
57
|
+
:get, 'i8', 8,
|
58
|
+
:get, 'i8', 16).should == [63, -1, 123]
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'sets multiple values with multiple command args' do
|
62
|
+
@redises.bitfield(@key, :set, 'i8', 0, 63,
|
63
|
+
:set, 'i8', 8, -1,
|
64
|
+
:set, 'i8', 16, 123).should == [78, 104, -59]
|
65
|
+
|
66
|
+
@redises.bitfield(@key, :get, 'i8', 0,
|
67
|
+
:get, 'i8', 8,
|
68
|
+
:get, 'i8', 16).should == [63, -1, 123]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'with an :incrby command' do
|
73
|
+
it 'returns the incremented by value for an 8 bit signed integer' do
|
74
|
+
@redises.bitfield(@key, :incrby, 'i8', 0, 1).should == [79]
|
75
|
+
@redises.bitfield(@key, :incrby, 'i8', 8, -1).should == [103]
|
76
|
+
@redises.bitfield(@key, :incrby, 'i8', 16, 5).should == [-54]
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'with an overflow of wrap (default)' do
|
80
|
+
context 'for a signed integer' do
|
81
|
+
it 'wraps the overflow to the minimum and increments from there' do
|
82
|
+
@redises.bitfield(@key, :get, 'i8', 24).should == [78]
|
83
|
+
@redises.bitfield(@key, :overflow, :wrap,
|
84
|
+
:incrby, 'i8', 0, 200).should == [22]
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'wraps the underflow to the maximum value and decrements from there' do
|
88
|
+
@redises.bitfield(@key, :overflow, :wrap,
|
89
|
+
:incrby, 'i8', 16, -200).should == [-3]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'for an unsigned integer' do
|
94
|
+
it 'wraps the overflow back to zero and increments from there' do
|
95
|
+
@redises.bitfield(@key, :get, 'u8', 24).should == [78]
|
96
|
+
@redises.bitfield(@key, :overflow, :wrap,
|
97
|
+
:incrby, 'u8', 24, 233).should == [55]
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'wraps the underflow to the maximum value and decrements from there' do
|
101
|
+
@redises.bitfield(@key, :get, 'u8', 32).should == [84]
|
102
|
+
@redises.bitfield(@key, :overflow, :wrap,
|
103
|
+
:incrby, 'u8', 32, -233).should == [107]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'with an overflow of sat' do
|
109
|
+
it 'sets the overflowed value to the maximum' do
|
110
|
+
@redises.bitfield(@key, :overflow, :sat,
|
111
|
+
:incrby, 'i8', 0, 256).should == [127]
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'sets the underflowed value to the minimum' do
|
115
|
+
@redises.bitfield(@key, :overflow, :sat,
|
116
|
+
:incrby, 'i8', 16, -256).should == [-128]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'with an overflow of fail' do
|
121
|
+
it 'raises a redis error on an out of range value' do
|
122
|
+
@redises.bitfield(@key, :overflow, :fail,
|
123
|
+
:incrby, 'i8', 0, 256).should == [nil]
|
124
|
+
|
125
|
+
@redises.bitfield(@key, :overflow, :fail,
|
126
|
+
:incrby, 'i8', 16, -256).should == [nil]
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'retains the original value after a failed increment' do
|
130
|
+
@redises.bitfield(@key, :get, 'i8', 0).should == [78]
|
131
|
+
@redises.bitfield(@key, :overflow, :fail,
|
132
|
+
:incrby, 'i8', 0, 256).should == [nil]
|
133
|
+
@redises.bitfield(@key, :get, 'i8', 0).should == [78]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'with multiple overflow commands in one transaction' do
|
138
|
+
it 'handles the overflow values correctly' do
|
139
|
+
@redises.bitfield(@key, :overflow, :sat,
|
140
|
+
:incrby, 'i8', 0, 256,
|
141
|
+
:incrby, 'i8', 8, -256,
|
142
|
+
:overflow, :wrap,
|
143
|
+
:incrby, 'i8', 0, 200,
|
144
|
+
:incrby, 'i8', 16, -200,
|
145
|
+
:overflow, :fail,
|
146
|
+
:incrby, 'i8', 0, 256,
|
147
|
+
:incrby, 'i8', 16, -256).should == [127, -128, 71, -3, nil, nil]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'with an unsupported overflow value' do
|
152
|
+
it 'raises an error' do
|
153
|
+
expect do
|
154
|
+
@redises.bitfield(@key, :overflow, :foo,
|
155
|
+
:incrby, 'i8', 0, 256)
|
156
|
+
end.to raise_error(Redis::CommandError)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'with a mixed set of commands' do
|
162
|
+
it 'returns the correct outputs' do
|
163
|
+
@redises.bitfield(@key, :set, 'i8', 0, 38,
|
164
|
+
:set, 'i8', 8, -99,
|
165
|
+
:incrby, 'i8', 16, 1,
|
166
|
+
:get, 'i8', 0).should == [78, 104, -58, 38]
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|