mock_redis 0.22.0 → 0.27.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 +4 -4
- data/.rubocop.yml +26 -5
- data/.rubocop_todo.yml +1 -1
- data/.travis.yml +1 -0
- data/CHANGELOG.md +31 -0
- data/Gemfile +4 -2
- data/lib/mock_redis.rb +1 -8
- data/lib/mock_redis/connection_method.rb +13 -0
- data/lib/mock_redis/database.rb +44 -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 +27 -20
- 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/lib/mock_redis/zset_methods.rb +34 -9
- data/mock_redis.gemspec +1 -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/dump_spec.rb +19 -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/pipelined_spec.rb +20 -0
- data/spec/commands/restore_spec.rb +47 -0
- data/spec/commands/set_spec.rb +59 -9
- data/spec/commands/setbit_spec.rb +1 -0
- data/spec/commands/setex_spec.rb +16 -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/zinterstore_spec.rb +34 -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/commands/zunionstore_spec.rb +33 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/redis_multiplexer.rb +2 -1
- data/spec/transactions_spec.rb +16 -0
- metadata +14 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b491b0b8e260ee631a3633b35154946ef5822a3310d6bc51ce977febe8559b8a
|
4
|
+
data.tar.gz: 795a9ec1aa340ee6b0733b3a539a0ff355dc5e71287f59ca03f2ae64ef9e770e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea3fd9aabe7c3afac9c358dbe97a2ffb78277a1d0dab830d6b9983404a1a9f3b2b47f97022441b62884ce01fb6557b1b5a8ca334378bc18ba6c0863b577a947a
|
7
|
+
data.tar.gz: 4a487e49858bed2684e8695affe470801de0a6247c1a7281c1f1f3a6913f59ebe38fffee8fa0a41142d20d65cb8339cbb4dd4c2d03ddc2ed5d538760f59fc959
|
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,36 @@
|
|
1
1
|
# MockRedis Changelog
|
2
2
|
|
3
|
+
### 0.27.0
|
4
|
+
|
5
|
+
* Fix handling of keyword arguments on Ruby 3 ([#199](https://github.com/sds/mock_redis/pull/199))
|
6
|
+
* Allow passing string `offset` to `setbit` ([#200](https://github.com/sds/mock_redis/pull/200))
|
7
|
+
* Add `connection` method ([#201](https://github.com/sds/mock_redis/pull/201))
|
8
|
+
|
9
|
+
### 0.26.0
|
10
|
+
|
11
|
+
* Add block and count support to `xread` ([#194](https://github.com/sds/mock_redis/pull/194))
|
12
|
+
|
13
|
+
### 0.25.0
|
14
|
+
|
15
|
+
* Add support for `xread` command ([#190](https://github.com/sds/mock_redis/pull/190))
|
16
|
+
* Fix `mget` to raise error when passing empty array ([#191](https://github.com/sds/mock_redis/pull/191))
|
17
|
+
* Fix `xadd` when `maxlen` is zero ([#192](https://github.com/sds/mock_redis/pull/192))
|
18
|
+
|
19
|
+
### 0.24.0
|
20
|
+
|
21
|
+
* Fix handling of blocks within `multi` blocks ([#185](https://github.com/sds/mock_redis/pull/185))
|
22
|
+
* Fix handling of multiple consecutive `?` characters in key pattern matching ([#186](https://github.com/sds/mock_redis/pull/186))
|
23
|
+
* Change `exists` to return an integer and add `exists?` ([#188](https://github.com/sds/mock_redis/pull/188))
|
24
|
+
|
25
|
+
### 0.23.0
|
26
|
+
|
27
|
+
* Raise error when `setex` called with negative timeout ([#174](https://github.com/sds/mock_redis/pull/174))
|
28
|
+
* Add support for `dump`/`restore` between MockRedis instances ([#176](https://github.com/sds/mock_redis/pull/176))
|
29
|
+
* Fix warnings for ZSET methods on Ruby 2.7 ([#177](https://github.com/sds/mock_redis/pull/177))
|
30
|
+
* Add support for returning time in pipelines ([#179](https://github.com/sds/mock_redis/pull/179))
|
31
|
+
* Fix SET methods to correct set milliseconds with `px` ([#180](https://github.com/sds/mock_redis/pull/180))
|
32
|
+
* Add support for unsorted sets within `zinterstore`/`zunionstore`([#182](https://github.com/sds/mock_redis/pull/182))
|
33
|
+
|
3
34
|
### 0.22.0
|
4
35
|
|
5
36
|
* Gracefully handle cursors larger than the collection size in scan commands ([#171](https://github.com/sds/mock_redis/pull/171))
|
data/Gemfile
CHANGED
@@ -4,9 +4,11 @@ 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
|
+
|
12
|
+
gem 'ruby2_keywords'
|
11
13
|
|
12
14
|
gem 'coveralls', require: false
|
data/lib/mock_redis.rb
CHANGED
@@ -64,13 +64,6 @@ class MockRedis
|
|
64
64
|
options[:db]
|
65
65
|
end
|
66
66
|
|
67
|
-
def now
|
68
|
-
current_time = options[:time_class].now
|
69
|
-
miliseconds = (current_time.to_r - current_time.to_i) * 1_000
|
70
|
-
[current_time.to_i, miliseconds.to_i]
|
71
|
-
end
|
72
|
-
alias time now
|
73
|
-
|
74
67
|
def time_at(timestamp)
|
75
68
|
options[:time_class].at(timestamp)
|
76
69
|
end
|
@@ -91,7 +84,7 @@ class MockRedis
|
|
91
84
|
super || @db.respond_to?(method, include_private)
|
92
85
|
end
|
93
86
|
|
94
|
-
def method_missing(method, *args, &block)
|
87
|
+
ruby2_keywords def method_missing(method, *args, &block)
|
95
88
|
@db.send(method, *args, &block)
|
96
89
|
end
|
97
90
|
|
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,33 @@ 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) }
|
131
|
+
'OK'
|
132
|
+
end
|
133
|
+
|
134
|
+
def dump(key)
|
135
|
+
value = data[key]
|
136
|
+
value ? Marshal.dump(value) : nil
|
137
|
+
end
|
138
|
+
|
139
|
+
def restore(key, ttl, value, replace: false)
|
140
|
+
if !replace && exists?(key)
|
141
|
+
raise Redis::CommandError, 'BUSYKEY Target key name already exists.'
|
142
|
+
end
|
143
|
+
data[key] = Marshal.load(value) # rubocop:disable Security/MarshalLoad
|
144
|
+
if ttl > 0
|
145
|
+
pexpire(key, ttl)
|
146
|
+
end
|
124
147
|
'OK'
|
125
148
|
end
|
126
149
|
|
@@ -143,11 +166,11 @@ class MockRedis
|
|
143
166
|
end
|
144
167
|
|
145
168
|
def lastsave
|
146
|
-
|
169
|
+
now.first
|
147
170
|
end
|
148
171
|
|
149
172
|
def persist(key)
|
150
|
-
if exists(key) && has_expiration?(key)
|
173
|
+
if exists?(key) && has_expiration?(key)
|
151
174
|
remove_expiration(key)
|
152
175
|
true
|
153
176
|
else
|
@@ -188,7 +211,7 @@ class MockRedis
|
|
188
211
|
raise Redis::CommandError, 'ERR no such key'
|
189
212
|
end
|
190
213
|
|
191
|
-
if exists(newkey)
|
214
|
+
if exists?(newkey)
|
192
215
|
false
|
193
216
|
else
|
194
217
|
rename(key, newkey)
|
@@ -201,7 +224,7 @@ class MockRedis
|
|
201
224
|
end
|
202
225
|
|
203
226
|
def ttl(key)
|
204
|
-
if !exists(key)
|
227
|
+
if !exists?(key)
|
205
228
|
-2
|
206
229
|
elsif has_expiration?(key)
|
207
230
|
now, = @base.now
|
@@ -215,7 +238,7 @@ class MockRedis
|
|
215
238
|
now, miliseconds = @base.now
|
216
239
|
now_ms = now * 1000 + miliseconds
|
217
240
|
|
218
|
-
if !exists(key)
|
241
|
+
if !exists?(key)
|
219
242
|
-2
|
220
243
|
elsif has_expiration?(key)
|
221
244
|
(expiration(key).to_r * 1000).to_i - now_ms
|
@@ -224,8 +247,15 @@ class MockRedis
|
|
224
247
|
end
|
225
248
|
end
|
226
249
|
|
250
|
+
def now
|
251
|
+
current_time = @base.options[:time_class].now
|
252
|
+
miliseconds = (current_time.to_r - current_time.to_i) * 1_000
|
253
|
+
[current_time.to_i, miliseconds.to_i]
|
254
|
+
end
|
255
|
+
alias time now
|
256
|
+
|
227
257
|
def type(key)
|
228
|
-
if !exists(key)
|
258
|
+
if !exists?(key)
|
229
259
|
'none'
|
230
260
|
elsif hashy?(key)
|
231
261
|
'hash'
|
@@ -300,7 +330,7 @@ class MockRedis
|
|
300
330
|
Regexp.new(
|
301
331
|
"^#{pattern}$".
|
302
332
|
gsub(/([+|()])/, '\\\\\1').
|
303
|
-
gsub(/(
|
333
|
+
gsub(/(?<!\\)\?/, '\\1.').
|
304
334
|
gsub(/([^\\])\*/, '\\1.*')
|
305
335
|
)
|
306
336
|
end
|
@@ -328,8 +358,8 @@ class MockRedis
|
|
328
358
|
# This method isn't private, but it also isn't a Redis command, so
|
329
359
|
# it doesn't belong up above with all the Redis commands.
|
330
360
|
def expire_keys
|
331
|
-
|
332
|
-
now_ms =
|
361
|
+
now_sec, miliseconds = now
|
362
|
+
now_ms = now_sec * 1_000 + miliseconds
|
333
363
|
|
334
364
|
to_delete = expire_times.take_while do |(time, _key)|
|
335
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)
|