mock_redis 0.23.0 → 0.27.1
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 +4 -4
- data/.rubocop.yml +26 -5
- data/.rubocop_todo.yml +1 -1
- data/.travis.yml +1 -0
- data/CHANGELOG.md +27 -0
- data/Gemfile +2 -2
- data/lib/mock_redis.rb +1 -1
- data/lib/mock_redis/connection_method.rb +13 -0
- data/lib/mock_redis/database.rb +21 -14
- data/lib/mock_redis/expire_wrapper.rb +1 -1
- data/lib/mock_redis/future.rb +1 -1
- data/lib/mock_redis/geospatial_methods.rb +5 -5
- data/lib/mock_redis/hash_methods.rb +9 -4
- data/lib/mock_redis/info_method.rb +2 -2
- data/lib/mock_redis/multi_db_wrapper.rb +3 -3
- data/lib/mock_redis/pipelined_wrapper.rb +1 -1
- data/lib/mock_redis/stream.rb +22 -2
- data/lib/mock_redis/stream/id.rb +1 -1
- data/lib/mock_redis/stream_methods.rb +16 -1
- data/lib/mock_redis/string_methods.rb +21 -17
- data/lib/mock_redis/transaction_wrapper.rb +3 -3
- data/lib/mock_redis/utility_methods.rb +1 -1
- data/lib/mock_redis/version.rb +1 -1
- data/mock_redis.gemspec +2 -1
- data/spec/commands/blpop_spec.rb +0 -6
- data/spec/commands/brpop_spec.rb +6 -5
- data/spec/commands/connection_spec.rb +15 -0
- data/spec/commands/del_spec.rb +17 -0
- data/spec/commands/exists_spec.rb +34 -5
- data/spec/commands/future_spec.rb +11 -1
- data/spec/commands/geoadd_spec.rb +1 -1
- data/spec/commands/hset_spec.rb +6 -6
- data/spec/commands/keys_spec.rb +17 -0
- data/spec/commands/mget_spec.rb +6 -0
- data/spec/commands/move_spec.rb +5 -5
- data/spec/commands/set_spec.rb +55 -7
- data/spec/commands/setbit_spec.rb +1 -0
- data/spec/commands/srandmember_spec.rb +1 -1
- data/spec/commands/xadd_spec.rb +23 -3
- data/spec/commands/xlen_spec.rb +3 -1
- data/spec/commands/xrange_spec.rb +13 -0
- data/spec/commands/xread_spec.rb +66 -0
- data/spec/commands/xtrim_spec.rb +6 -0
- data/spec/commands/zrange_spec.rb +1 -1
- data/spec/commands/zrangebyscore_spec.rb +1 -1
- data/spec/commands/zrevrange_spec.rb +1 -1
- data/spec/commands/zrevrangebyscore_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/support/redis_multiplexer.rb +2 -1
- data/spec/transactions_spec.rb +16 -0
- metadata +24 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbd4308bd9413896742121468e39d64096e55b7760453a4220696aaa0554e38e
|
4
|
+
data.tar.gz: 0f8e0c66ac4533044ad91ee89a383bba1297cc186fdf514c66923a6188024b0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fde8339234a0e1c8022cd63208e8e279cc834ff4280c6690d85a516259f7c29ac36fd3882a433a94af4e4e0bb584a7c332c823cc54db59556b17e7bf42d2f97
|
7
|
+
data.tar.gz: 4f7d508739c4eef78afa8e155d2ec4166f5b5b644f37f846a59f9b555c34bb948d545fca55c3d2c7dae2781fe90c24c7fabb804b3406f97030e8ee4e68eff9f4
|
data/.rubocop.yml
CHANGED
@@ -3,10 +3,10 @@ inherit_from: .rubocop_todo.yml
|
|
3
3
|
AllCops:
|
4
4
|
TargetRubyVersion: 2.4
|
5
5
|
|
6
|
-
Layout/
|
6
|
+
Layout/ArgumentAlignment:
|
7
7
|
Enabled: false
|
8
8
|
|
9
|
-
Layout/
|
9
|
+
Layout/ParameterAlignment:
|
10
10
|
Enabled: false
|
11
11
|
|
12
12
|
Layout/DotPosition:
|
@@ -15,9 +15,21 @@ Layout/DotPosition:
|
|
15
15
|
Layout/EmptyLineAfterGuardClause:
|
16
16
|
Enabled: false
|
17
17
|
|
18
|
+
Layout/LineLength:
|
19
|
+
Max: 100
|
20
|
+
|
21
|
+
Layout/SpaceAroundMethodCallOperator:
|
22
|
+
Enabled: true
|
23
|
+
|
18
24
|
Lint/AssignmentInCondition:
|
19
25
|
Enabled: false
|
20
26
|
|
27
|
+
Lint/RaiseException:
|
28
|
+
Enabled: true
|
29
|
+
|
30
|
+
Lint/StructNewOverride:
|
31
|
+
Enabled: true
|
32
|
+
|
21
33
|
# We use this a lot in specs where it's perfectly valid
|
22
34
|
Lint/Void:
|
23
35
|
Exclude:
|
@@ -35,9 +47,6 @@ Metrics/CyclomaticComplexity:
|
|
35
47
|
Metrics/ClassLength:
|
36
48
|
Enabled: false
|
37
49
|
|
38
|
-
Metrics/LineLength:
|
39
|
-
Max: 100
|
40
|
-
|
41
50
|
Metrics/MethodLength:
|
42
51
|
Enabled: false
|
43
52
|
|
@@ -57,6 +66,18 @@ Style/Documentation:
|
|
57
66
|
Style/DoubleNegation:
|
58
67
|
Enabled: false
|
59
68
|
|
69
|
+
Style/ExponentialNotation:
|
70
|
+
Enabled: true
|
71
|
+
|
72
|
+
Style/HashEachMethods:
|
73
|
+
Enabled: true
|
74
|
+
|
75
|
+
Style/HashTransformKeys:
|
76
|
+
Enabled: true
|
77
|
+
|
78
|
+
Style/HashTransformValues:
|
79
|
+
Enabled: true
|
80
|
+
|
60
81
|
# We have too much code that relies on modifying strings
|
61
82
|
Style/FrozenStringLiteralComment:
|
62
83
|
Enabled: false
|
data/.rubocop_todo.yml
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
# Offense count: 17
|
10
10
|
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
11
11
|
# AllowedNames: io, id, to, by, on, in, at, ip
|
12
|
-
Naming/
|
12
|
+
Naming/MethodParameterName:
|
13
13
|
Exclude:
|
14
14
|
- 'lib/mock_redis/database.rb'
|
15
15
|
- 'lib/mock_redis/expire_wrapper.rb'
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
# MockRedis Changelog
|
2
2
|
|
3
|
+
### 0.27.1
|
4
|
+
|
5
|
+
* Fix missing `ruby2_keywords` gem
|
6
|
+
* Allow passing string `offset` to `getbit` ([#203](https://github.com/sds/mock_redis/pull/203))
|
7
|
+
|
8
|
+
### 0.27.0
|
9
|
+
|
10
|
+
* Fix handling of keyword arguments on Ruby 3 ([#199](https://github.com/sds/mock_redis/pull/199))
|
11
|
+
* Allow passing string `offset` to `setbit` ([#200](https://github.com/sds/mock_redis/pull/200))
|
12
|
+
* Add `connection` method ([#201](https://github.com/sds/mock_redis/pull/201))
|
13
|
+
|
14
|
+
### 0.26.0
|
15
|
+
|
16
|
+
* Add block and count support to `xread` ([#194](https://github.com/sds/mock_redis/pull/194))
|
17
|
+
|
18
|
+
### 0.25.0
|
19
|
+
|
20
|
+
* Add support for `xread` command ([#190](https://github.com/sds/mock_redis/pull/190))
|
21
|
+
* Fix `mget` to raise error when passing empty array ([#191](https://github.com/sds/mock_redis/pull/191))
|
22
|
+
* Fix `xadd` when `maxlen` is zero ([#192](https://github.com/sds/mock_redis/pull/192))
|
23
|
+
|
24
|
+
### 0.24.0
|
25
|
+
|
26
|
+
* Fix handling of blocks within `multi` blocks ([#185](https://github.com/sds/mock_redis/pull/185))
|
27
|
+
* Fix handling of multiple consecutive `?` characters in key pattern matching ([#186](https://github.com/sds/mock_redis/pull/186))
|
28
|
+
* Change `exists` to return an integer and add `exists?` ([#188](https://github.com/sds/mock_redis/pull/188))
|
29
|
+
|
3
30
|
### 0.23.0
|
4
31
|
|
5
32
|
* Raise error when `setex` called with negative timeout ([#174](https://github.com/sds/mock_redis/pull/174))
|
data/Gemfile
CHANGED
@@ -4,9 +4,9 @@ source 'http://rubygems.org'
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
# Run all pre-commit hooks via Overcommit during CI runs
|
7
|
-
gem 'overcommit', '0.
|
7
|
+
gem 'overcommit', '0.53.0'
|
8
8
|
|
9
9
|
# Pin tool versions (which are executed by Overcommit) for Travis builds
|
10
|
-
gem 'rubocop', '0.
|
10
|
+
gem 'rubocop', '0.82.0'
|
11
11
|
|
12
12
|
gem 'coveralls', require: false
|
data/lib/mock_redis.rb
CHANGED
data/lib/mock_redis/database.rb
CHANGED
@@ -11,6 +11,7 @@ require 'mock_redis/info_method'
|
|
11
11
|
require 'mock_redis/utility_methods'
|
12
12
|
require 'mock_redis/geospatial_methods'
|
13
13
|
require 'mock_redis/stream_methods'
|
14
|
+
require 'mock_redis/connection_method'
|
14
15
|
|
15
16
|
class MockRedis
|
16
17
|
class Database
|
@@ -24,6 +25,7 @@ class MockRedis
|
|
24
25
|
include UtilityMethods
|
25
26
|
include GeospatialMethods
|
26
27
|
include StreamMethods
|
28
|
+
include ConnectionMethod
|
27
29
|
|
28
30
|
attr_reader :data, :expire_times
|
29
31
|
|
@@ -35,7 +37,7 @@ class MockRedis
|
|
35
37
|
|
36
38
|
def initialize_copy(_source)
|
37
39
|
@data = @data.clone
|
38
|
-
@data.
|
40
|
+
@data.each_key { |k| @data[k] = @data[k].clone }
|
39
41
|
@expire_times = @expire_times.map(&:clone)
|
40
42
|
end
|
41
43
|
|
@@ -106,7 +108,7 @@ class MockRedis
|
|
106
108
|
raise Redis::CommandError, 'ERR value is not an integer or out of range'
|
107
109
|
end
|
108
110
|
|
109
|
-
if exists(key)
|
111
|
+
if exists?(key)
|
110
112
|
timestamp = Rational(timestamp_ms.to_i, 1000)
|
111
113
|
set_expiration(key, @base.time_at(timestamp))
|
112
114
|
true
|
@@ -115,12 +117,17 @@ class MockRedis
|
|
115
117
|
end
|
116
118
|
end
|
117
119
|
|
118
|
-
def exists(
|
119
|
-
data.key?(key)
|
120
|
+
def exists(*keys)
|
121
|
+
keys.count { |key| data.key?(key) }
|
122
|
+
end
|
123
|
+
|
124
|
+
def exists?(*keys)
|
125
|
+
keys.each { |key| return true if data.key?(key) }
|
126
|
+
false
|
120
127
|
end
|
121
128
|
|
122
129
|
def flushdb
|
123
|
-
data.
|
130
|
+
data.each_key { |k| del(k) }
|
124
131
|
'OK'
|
125
132
|
end
|
126
133
|
|
@@ -130,7 +137,7 @@ class MockRedis
|
|
130
137
|
end
|
131
138
|
|
132
139
|
def restore(key, ttl, value, replace: false)
|
133
|
-
if !replace && exists(key)
|
140
|
+
if !replace && exists?(key)
|
134
141
|
raise Redis::CommandError, 'BUSYKEY Target key name already exists.'
|
135
142
|
end
|
136
143
|
data[key] = Marshal.load(value) # rubocop:disable Security/MarshalLoad
|
@@ -163,7 +170,7 @@ class MockRedis
|
|
163
170
|
end
|
164
171
|
|
165
172
|
def persist(key)
|
166
|
-
if exists(key) && has_expiration?(key)
|
173
|
+
if exists?(key) && has_expiration?(key)
|
167
174
|
remove_expiration(key)
|
168
175
|
true
|
169
176
|
else
|
@@ -204,7 +211,7 @@ class MockRedis
|
|
204
211
|
raise Redis::CommandError, 'ERR no such key'
|
205
212
|
end
|
206
213
|
|
207
|
-
if exists(newkey)
|
214
|
+
if exists?(newkey)
|
208
215
|
false
|
209
216
|
else
|
210
217
|
rename(key, newkey)
|
@@ -217,7 +224,7 @@ class MockRedis
|
|
217
224
|
end
|
218
225
|
|
219
226
|
def ttl(key)
|
220
|
-
if !exists(key)
|
227
|
+
if !exists?(key)
|
221
228
|
-2
|
222
229
|
elsif has_expiration?(key)
|
223
230
|
now, = @base.now
|
@@ -231,7 +238,7 @@ class MockRedis
|
|
231
238
|
now, miliseconds = @base.now
|
232
239
|
now_ms = now * 1000 + miliseconds
|
233
240
|
|
234
|
-
if !exists(key)
|
241
|
+
if !exists?(key)
|
235
242
|
-2
|
236
243
|
elsif has_expiration?(key)
|
237
244
|
(expiration(key).to_r * 1000).to_i - now_ms
|
@@ -248,7 +255,7 @@ class MockRedis
|
|
248
255
|
alias time now
|
249
256
|
|
250
257
|
def type(key)
|
251
|
-
if !exists(key)
|
258
|
+
if !exists?(key)
|
252
259
|
'none'
|
253
260
|
elsif hashy?(key)
|
254
261
|
'hash'
|
@@ -323,7 +330,7 @@ class MockRedis
|
|
323
330
|
Regexp.new(
|
324
331
|
"^#{pattern}$".
|
325
332
|
gsub(/([+|()])/, '\\\\\1').
|
326
|
-
gsub(/(
|
333
|
+
gsub(/(?<!\\)\?/, '\\1.').
|
327
334
|
gsub(/([^\\])\*/, '\\1.*')
|
328
335
|
)
|
329
336
|
end
|
@@ -351,8 +358,8 @@ class MockRedis
|
|
351
358
|
# This method isn't private, but it also isn't a Redis command, so
|
352
359
|
# it doesn't belong up above with all the Redis commands.
|
353
360
|
def expire_keys
|
354
|
-
|
355
|
-
now_ms =
|
361
|
+
now_sec, miliseconds = now
|
362
|
+
now_ms = now_sec * 1_000 + miliseconds
|
356
363
|
|
357
364
|
to_delete = expire_times.take_while do |(time, _key)|
|
358
365
|
(time.to_r * 1_000).to_i <= now_ms
|
data/lib/mock_redis/future.rb
CHANGED
@@ -12,7 +12,7 @@ class MockRedis
|
|
12
12
|
D_R = Math::PI / 180.0
|
13
13
|
EARTH_RADIUS_IN_METERS = 6_372_797.560856
|
14
14
|
|
15
|
-
def geoadd(key, *args)
|
15
|
+
ruby2_keywords def geoadd(key, *args)
|
16
16
|
points = parse_points(args)
|
17
17
|
|
18
18
|
scored_points = points.map do |point|
|
@@ -38,7 +38,7 @@ class MockRedis
|
|
38
38
|
lng2, lat2 = geohash_decode(hash2)
|
39
39
|
|
40
40
|
distance = geohash_distance(lng1, lat1, lng2, lat2) / to_meter
|
41
|
-
format('
|
41
|
+
format('%<distance>.4f', distance: distance)
|
42
42
|
end
|
43
43
|
|
44
44
|
def geohash(key, members)
|
@@ -95,8 +95,8 @@ class MockRedis
|
|
95
95
|
lat = Float(point[1])
|
96
96
|
|
97
97
|
unless LNG_RANGE.include?(lng) && LAT_RANGE.include?(lat)
|
98
|
-
lng = format('
|
99
|
-
lat = format('
|
98
|
+
lng = format('%<long>.6f', long: lng)
|
99
|
+
lat = format('%<lat>.6f', lat: lat)
|
100
100
|
raise Redis::CommandError,
|
101
101
|
"ERR invalid longitude,latitude pair #{lng},#{lat}"
|
102
102
|
end
|
@@ -201,7 +201,7 @@ class MockRedis
|
|
201
201
|
end
|
202
202
|
|
203
203
|
def format_decoded_coord(coord)
|
204
|
-
coord = format('
|
204
|
+
coord = format('%<coord>.17f', coord: coord)
|
205
205
|
l = 1
|
206
206
|
l += 1 while coord[-l] == '0'
|
207
207
|
coord = coord[0..-l]
|
@@ -128,10 +128,15 @@ class MockRedis
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
-
def hset(key,
|
132
|
-
|
133
|
-
with_hash_at(key)
|
134
|
-
|
131
|
+
def hset(key, *args)
|
132
|
+
added = 0
|
133
|
+
with_hash_at(key) do |hash|
|
134
|
+
args.each_slice(2) do |field, value|
|
135
|
+
added += 1 unless hash.key?(field.to_s)
|
136
|
+
hash[field.to_s] = value.to_s
|
137
|
+
end
|
138
|
+
end
|
139
|
+
added
|
135
140
|
end
|
136
141
|
|
137
142
|
def hsetnx(key, field, value)
|
@@ -83,7 +83,7 @@ class MockRedis
|
|
83
83
|
|
84
84
|
# The Ruby Redis client returns commandstats differently when it's called as
|
85
85
|
# "INFO commandstats".
|
86
|
-
# rubocop:disable
|
86
|
+
# rubocop:disable Layout/LineLength
|
87
87
|
COMMAND_STATS_SOLO_INFO = {
|
88
88
|
'auth' => { 'calls' => '572501', 'usec' => '2353163', 'usec_per_call' => '4.11' },
|
89
89
|
'client' => { 'calls' => '1', 'usec' => '80', 'usec_per_call' => '80.00' },
|
@@ -123,7 +123,7 @@ class MockRedis
|
|
123
123
|
'cmdstat_smembers' => 'calls=58,usec=231,usec_per_call=3.98',
|
124
124
|
'cmdstat_sunionstore' => 'calls=4185027,usec=11762454022,usec_per_call=2810.60',
|
125
125
|
}.freeze
|
126
|
-
# rubocop:enable
|
126
|
+
# rubocop:enable Layout/LineLength
|
127
127
|
|
128
128
|
DEFAULT_INFO = [
|
129
129
|
SERVER_INFO,
|
@@ -17,14 +17,14 @@ class MockRedis
|
|
17
17
|
super || current_db.respond_to?(method, include_private)
|
18
18
|
end
|
19
19
|
|
20
|
-
def method_missing(method, *args, &block)
|
20
|
+
ruby2_keywords def method_missing(method, *args, &block)
|
21
21
|
current_db.send(method, *args, &block)
|
22
22
|
end
|
23
23
|
|
24
24
|
def initialize_copy(source)
|
25
25
|
super
|
26
26
|
@databases = @databases.clone
|
27
|
-
@databases.
|
27
|
+
@databases.each_key do |k|
|
28
28
|
@databases[k] = @databases[k].clone
|
29
29
|
end
|
30
30
|
end
|
@@ -39,7 +39,7 @@ class MockRedis
|
|
39
39
|
src = current_db
|
40
40
|
dest = db(db_index)
|
41
41
|
|
42
|
-
if !src.exists(key) || dest.exists(key)
|
42
|
+
if !src.exists?(key) || dest.exists?(key)
|
43
43
|
false
|
44
44
|
else
|
45
45
|
case current_db.type(key)
|
@@ -18,7 +18,7 @@ class MockRedis
|
|
18
18
|
@pipelined_futures = @pipelined_futures.clone
|
19
19
|
end
|
20
20
|
|
21
|
-
def method_missing(method, *args, &block)
|
21
|
+
ruby2_keywords def method_missing(method, *args, &block)
|
22
22
|
if in_pipeline?
|
23
23
|
future = MockRedis::Future.new([method, *args], block)
|
24
24
|
@pipelined_futures << future
|
data/lib/mock_redis/stream.rb
CHANGED
@@ -23,14 +23,26 @@ class MockRedis
|
|
23
23
|
|
24
24
|
def add(id, values)
|
25
25
|
@last_id = MockRedis::Stream::Id.new(id, min: @last_id)
|
26
|
+
if @last_id.to_s == '0-0'
|
27
|
+
raise Redis::CommandError,
|
28
|
+
'ERR The ID specified in XADD must be greater than 0-0'
|
29
|
+
end
|
26
30
|
members.add [@last_id, Hash[values.map { |k, v| [k.to_s, v.to_s] }]]
|
27
31
|
@last_id.to_s
|
28
32
|
end
|
29
33
|
|
30
34
|
def trim(count)
|
31
35
|
deleted = @members.size - count
|
32
|
-
|
33
|
-
|
36
|
+
if deleted > 0
|
37
|
+
@members = if count == 0
|
38
|
+
Set.new
|
39
|
+
else
|
40
|
+
@members.to_a[-count..-1].to_set
|
41
|
+
end
|
42
|
+
deleted
|
43
|
+
else
|
44
|
+
0
|
45
|
+
end
|
34
46
|
end
|
35
47
|
|
36
48
|
def range(start, finish, reversed, *opts_in)
|
@@ -45,6 +57,14 @@ class MockRedis
|
|
45
57
|
items
|
46
58
|
end
|
47
59
|
|
60
|
+
def read(id, *opts_in)
|
61
|
+
opts = options opts_in, %w[count block]
|
62
|
+
stream_id = MockRedis::Stream::Id.new(id)
|
63
|
+
items = members.select { |m| (stream_id < m[0]) }.map { |m| [m[0].to_s, m[1]] }
|
64
|
+
return items.first(opts['count'].to_i) if opts.key?('count')
|
65
|
+
items
|
66
|
+
end
|
67
|
+
|
48
68
|
def each
|
49
69
|
members.each { |m| yield m }
|
50
70
|
end
|