mock_redis 0.19.0 → 0.44.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/CHANGELOG.md +161 -0
- data/LICENSE.md +21 -0
- data/README.md +41 -17
- data/lib/mock_redis/connection_method.rb +13 -0
- data/lib/mock_redis/database.rb +116 -41
- data/lib/mock_redis/expire_wrapper.rb +1 -1
- data/lib/mock_redis/future.rb +1 -1
- data/lib/mock_redis/geospatial_methods.rb +13 -21
- data/lib/mock_redis/hash_methods.rb +34 -15
- data/lib/mock_redis/indifferent_hash.rb +0 -8
- data/lib/mock_redis/info_method.rb +2 -2
- data/lib/mock_redis/list_methods.rb +39 -4
- data/lib/mock_redis/memory_method.rb +11 -0
- data/lib/mock_redis/multi_db_wrapper.rb +4 -4
- data/lib/mock_redis/pipelined_wrapper.rb +32 -15
- data/lib/mock_redis/set_methods.rb +34 -6
- 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 +81 -30
- data/lib/mock_redis/transaction_wrapper.rb +32 -21
- data/lib/mock_redis/utility_methods.rb +9 -4
- data/lib/mock_redis/version.rb +1 -1
- data/lib/mock_redis/zset.rb +5 -8
- data/lib/mock_redis/zset_methods.rb +64 -12
- data/lib/mock_redis.rb +38 -10
- metadata +40 -336
- data/.gitignore +0 -5
- data/.mailmap +0 -2
- data/.overcommit.yml +0 -21
- data/.rspec +0 -1
- data/.rubocop.yml +0 -121
- data/.rubocop_todo.yml +0 -35
- data/.simplecov +0 -4
- data/.travis.yml +0 -33
- data/Gemfile +0 -12
- data/LICENSE +0 -19
- data/Rakefile +0 -2
- data/mock_redis.gemspec +0 -30
- data/spec/client_spec.rb +0 -17
- data/spec/cloning_spec.rb +0 -95
- data/spec/commands/append_spec.rb +0 -24
- data/spec/commands/auth_spec.rb +0 -7
- data/spec/commands/bgrewriteaof_spec.rb +0 -7
- data/spec/commands/bgsave_spec.rb +0 -7
- data/spec/commands/bitcount_spec.rb +0 -25
- data/spec/commands/bitfield_spec.rb +0 -169
- data/spec/commands/blpop_spec.rb +0 -59
- data/spec/commands/brpop_spec.rb +0 -58
- data/spec/commands/brpoplpush_spec.rb +0 -52
- data/spec/commands/connected_spec.rb +0 -7
- data/spec/commands/dbsize_spec.rb +0 -18
- data/spec/commands/decr_spec.rb +0 -34
- data/spec/commands/decrby_spec.rb +0 -34
- data/spec/commands/del_spec.rb +0 -35
- data/spec/commands/disconnect_spec.rb +0 -7
- data/spec/commands/echo_spec.rb +0 -11
- data/spec/commands/eval_spec.rb +0 -7
- data/spec/commands/evalsha_spec.rb +0 -10
- data/spec/commands/exists_spec.rb +0 -14
- data/spec/commands/expire_spec.rb +0 -111
- data/spec/commands/expireat_spec.rb +0 -47
- data/spec/commands/flushall_spec.rb +0 -38
- data/spec/commands/flushdb_spec.rb +0 -38
- data/spec/commands/future_spec.rb +0 -20
- data/spec/commands/geoadd_spec.rb +0 -58
- data/spec/commands/geodist_spec.rb +0 -114
- data/spec/commands/geohash_spec.rb +0 -52
- data/spec/commands/geopos_spec.rb +0 -55
- data/spec/commands/get_spec.rb +0 -30
- data/spec/commands/getbit_spec.rb +0 -34
- data/spec/commands/getrange_spec.rb +0 -22
- data/spec/commands/getset_spec.rb +0 -23
- data/spec/commands/hash_operator_spec.rb +0 -21
- data/spec/commands/hdel_spec.rb +0 -54
- data/spec/commands/hexists_spec.rb +0 -27
- data/spec/commands/hget_spec.rb +0 -28
- data/spec/commands/hgetall_spec.rb +0 -32
- data/spec/commands/hincrby_spec.rb +0 -58
- data/spec/commands/hincrbyfloat_spec.rb +0 -58
- data/spec/commands/hkeys_spec.rb +0 -19
- data/spec/commands/hlen_spec.rb +0 -19
- data/spec/commands/hmget_spec.rb +0 -40
- data/spec/commands/hmset_spec.rb +0 -43
- data/spec/commands/hscan_each_spec.rb +0 -48
- data/spec/commands/hscan_spec.rb +0 -27
- data/spec/commands/hset_spec.rb +0 -38
- data/spec/commands/hsetnx_spec.rb +0 -44
- data/spec/commands/hvals_spec.rb +0 -19
- data/spec/commands/incr_spec.rb +0 -34
- data/spec/commands/incrby_spec.rb +0 -44
- data/spec/commands/incrbyfloat_spec.rb +0 -44
- data/spec/commands/info_spec.rb +0 -62
- data/spec/commands/keys_spec.rb +0 -122
- data/spec/commands/lastsave_spec.rb +0 -8
- data/spec/commands/lindex_spec.rb +0 -49
- data/spec/commands/linsert_spec.rb +0 -68
- data/spec/commands/llen_spec.rb +0 -16
- data/spec/commands/lpop_spec.rb +0 -34
- data/spec/commands/lpush_spec.rb +0 -43
- data/spec/commands/lpushx_spec.rb +0 -46
- data/spec/commands/lrange_spec.rb +0 -51
- data/spec/commands/lrem_spec.rb +0 -80
- data/spec/commands/lset_spec.rb +0 -43
- data/spec/commands/ltrim_spec.rb +0 -45
- data/spec/commands/mapped_hmget_spec.rb +0 -29
- data/spec/commands/mapped_hmset_spec.rb +0 -47
- data/spec/commands/mapped_mget_spec.rb +0 -22
- data/spec/commands/mapped_mset_spec.rb +0 -19
- data/spec/commands/mapped_msetnx_spec.rb +0 -26
- data/spec/commands/mget_spec.rb +0 -34
- data/spec/commands/move_spec.rb +0 -147
- data/spec/commands/mset_spec.rb +0 -29
- data/spec/commands/msetnx_spec.rb +0 -40
- data/spec/commands/persist_spec.rb +0 -48
- data/spec/commands/pexpire_spec.rb +0 -86
- data/spec/commands/pexpireat_spec.rb +0 -48
- data/spec/commands/ping_spec.rb +0 -7
- data/spec/commands/pipelined_spec.rb +0 -42
- data/spec/commands/pttl_spec.rb +0 -41
- data/spec/commands/quit_spec.rb +0 -7
- data/spec/commands/randomkey_spec.rb +0 -20
- data/spec/commands/rename_spec.rb +0 -42
- data/spec/commands/renamenx_spec.rb +0 -41
- data/spec/commands/rpop_spec.rb +0 -34
- data/spec/commands/rpoplpush_spec.rb +0 -50
- data/spec/commands/rpush_spec.rb +0 -43
- data/spec/commands/rpushx_spec.rb +0 -46
- data/spec/commands/sadd_spec.rb +0 -45
- data/spec/commands/save_spec.rb +0 -7
- data/spec/commands/scan_each_spec.rb +0 -39
- data/spec/commands/scan_spec.rb +0 -55
- data/spec/commands/scard_spec.rb +0 -18
- data/spec/commands/script_spec.rb +0 -9
- data/spec/commands/sdiff_spec.rb +0 -47
- data/spec/commands/sdiffstore_spec.rb +0 -58
- data/spec/commands/select_spec.rb +0 -61
- data/spec/commands/set_spec.rb +0 -63
- data/spec/commands/setbit_spec.rb +0 -54
- data/spec/commands/setex_spec.rb +0 -22
- data/spec/commands/setnx_spec.rb +0 -25
- data/spec/commands/setrange_spec.rb +0 -30
- data/spec/commands/sinter_spec.rb +0 -39
- data/spec/commands/sinterstore_spec.rb +0 -53
- data/spec/commands/sismember_spec.rb +0 -29
- data/spec/commands/smembers_spec.rb +0 -28
- data/spec/commands/smove_spec.rb +0 -41
- data/spec/commands/sort_list_spec.rb +0 -21
- data/spec/commands/sort_set_spec.rb +0 -21
- data/spec/commands/sort_zset_spec.rb +0 -21
- data/spec/commands/spop_spec.rb +0 -25
- data/spec/commands/srandmember_spec.rb +0 -49
- data/spec/commands/srem_spec.rb +0 -40
- data/spec/commands/sscan_each_spec.rb +0 -48
- data/spec/commands/sscan_spec.rb +0 -39
- data/spec/commands/strlen_spec.rb +0 -18
- data/spec/commands/sunion_spec.rb +0 -42
- data/spec/commands/sunionstore_spec.rb +0 -59
- data/spec/commands/ttl_spec.rb +0 -40
- data/spec/commands/type_spec.rb +0 -36
- data/spec/commands/unwatch_spec.rb +0 -7
- data/spec/commands/watch_spec.rb +0 -16
- data/spec/commands/zadd_spec.rb +0 -123
- data/spec/commands/zcard_spec.rb +0 -19
- data/spec/commands/zcount_spec.rb +0 -39
- data/spec/commands/zincrby_spec.rb +0 -31
- data/spec/commands/zinterstore_spec.rb +0 -96
- data/spec/commands/zrange_spec.rb +0 -80
- data/spec/commands/zrangebyscore_spec.rb +0 -83
- data/spec/commands/zrank_spec.rb +0 -29
- data/spec/commands/zrem_spec.rb +0 -43
- data/spec/commands/zremrangebyrank_spec.rb +0 -27
- data/spec/commands/zremrangebyscore_spec.rb +0 -35
- data/spec/commands/zrevrange_spec.rb +0 -56
- data/spec/commands/zrevrangebyscore_spec.rb +0 -58
- data/spec/commands/zrevrank_spec.rb +0 -29
- data/spec/commands/zscan_each_spec.rb +0 -48
- data/spec/commands/zscan_spec.rb +0 -26
- data/spec/commands/zscore_spec.rb +0 -22
- data/spec/commands/zunionstore_spec.rb +0 -104
- data/spec/mock_redis_spec.rb +0 -86
- data/spec/spec_helper.rb +0 -63
- data/spec/support/redis_multiplexer.rb +0 -106
- data/spec/support/shared_examples/only_operates_on_hashes.rb +0 -13
- data/spec/support/shared_examples/only_operates_on_lists.rb +0 -13
- data/spec/support/shared_examples/only_operates_on_sets.rb +0 -13
- data/spec/support/shared_examples/only_operates_on_strings.rb +0 -13
- data/spec/support/shared_examples/only_operates_on_zsets.rb +0 -57
- data/spec/support/shared_examples/sorts_enumerables.rb +0 -56
- data/spec/transactions_spec.rb +0 -159
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e495091d84ea1fec4bf5206d2a02e32c446ef0bd89b0feaed38f31d95b142b2
|
4
|
+
data.tar.gz: 696f65058fe29cd5fa849363b6cfa60454a432c0d392f530ac1494cba31ff062
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78b558108b350dc35df4d1f202e96326096394f9e23d89398d07cdbb33c6b088e0089467b14624a9e2c73210406457e291ab0cb09495a8d12a854df5ab8da1c3
|
7
|
+
data.tar.gz: f7e6d3021a4f2f5dd78e53d126ecea26fa7d3f8903bbcf96b0cf2a03b74049acbb169a18ff571c2aab18a0678cf57b90908d06b8c0e10039e00fce5b6050ad26
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,166 @@
|
|
1
1
|
# MockRedis Changelog
|
2
2
|
|
3
|
+
### 0.44.0
|
4
|
+
|
5
|
+
* Add suppore for `memory usage` command
|
6
|
+
|
7
|
+
### 0.43.0
|
8
|
+
|
9
|
+
* Fix issue when using with `redis-store` gem
|
10
|
+
|
11
|
+
### 0.42.0
|
12
|
+
|
13
|
+
* Drop support for Ruby 2.x
|
14
|
+
* Add support for `srem?`
|
15
|
+
|
16
|
+
### 0.41.0
|
17
|
+
|
18
|
+
* Add support for `expire`-related command options `nx`/`xx`/`lt`/`gt`
|
19
|
+
|
20
|
+
### 0.40.0
|
21
|
+
|
22
|
+
* Add support for `call` method name to be case insensitive
|
23
|
+
* Add support for `zmscore`
|
24
|
+
|
25
|
+
### 0.39.0
|
26
|
+
|
27
|
+
* Add support for calling `call` in `pipelined` block
|
28
|
+
* Fix `sadd` to stringify array
|
29
|
+
|
30
|
+
### 0.38.0
|
31
|
+
|
32
|
+
* Fix detection of stream key types
|
33
|
+
* Add support for `EXAT` AND `PXAT` arguments to `SET` command
|
34
|
+
|
35
|
+
### 0.37.0
|
36
|
+
|
37
|
+
* Require Ruby 2.7 or newer, since Ruby 2.6 and older are EOL
|
38
|
+
* Remove unnecessary files from gem contents
|
39
|
+
* Add support for popping multiple items with `lpop`
|
40
|
+
* Add support for `scan` with type option
|
41
|
+
* Add support for `sadd?`
|
42
|
+
* Add support for scanning on keys containing hash tags (`{...}`)
|
43
|
+
|
44
|
+
### 0.36.0
|
45
|
+
|
46
|
+
* Add support for `smismember`
|
47
|
+
* Add support for `lmove` and `blmove`
|
48
|
+
* Fix `zrem` to support passing array of integers
|
49
|
+
|
50
|
+
### 0.35.0
|
51
|
+
|
52
|
+
* Add support for `getdel`
|
53
|
+
|
54
|
+
### 0.34.0
|
55
|
+
|
56
|
+
* Add support for `with`
|
57
|
+
|
58
|
+
### 0.33.0
|
59
|
+
|
60
|
+
* Add support for `GET` argument to `SET` command
|
61
|
+
|
62
|
+
### 0.32.0
|
63
|
+
|
64
|
+
* Add support for `psetex`
|
65
|
+
|
66
|
+
### 0.31.0
|
67
|
+
|
68
|
+
* Allow `ping` to take argument
|
69
|
+
* Raise `CommandError` on `hmget` with empty list of fields
|
70
|
+
|
71
|
+
### 0.30.0
|
72
|
+
|
73
|
+
* Drop support for Ruby 2.4 and Ruby 2.5 since they are EOL
|
74
|
+
* Fix `expire` to to raise error on invalid integer
|
75
|
+
|
76
|
+
### 0.29.0
|
77
|
+
|
78
|
+
* Add support for `logger` option ([#211](https://github.com/sds/mock_redis/pull/211))
|
79
|
+
* Fix `zadd` to not perform conditional type conversion ([#214](https://github.com/sds/mock_redis/pull/214))
|
80
|
+
* Fix `hdel` to raise error when called with empty array ([#215](https://github.com/sds/mock_redis/pull/215))
|
81
|
+
|
82
|
+
### 0.28.0
|
83
|
+
|
84
|
+
* Fix `hmset` exception ([#206](https://github.com/sds/mock_redis/pull/206))
|
85
|
+
* Fix `hmset` to accept hashes in addition to key/value pairs ([#208](https://github.com/sds/mock_redis/pull/208))
|
86
|
+
* Fix stream ID regex to support `(` ([#209](https://github.com/sds/mock_redis/pull/209))
|
87
|
+
* Allow `mget` to accept a block ([#210](https://github.com/sds/mock_redis/pull/210))
|
88
|
+
|
89
|
+
### 0.27.3
|
90
|
+
|
91
|
+
* Ensure `ruby2_keywords` dependency is `require`d at runtime
|
92
|
+
|
93
|
+
### 0.27.2
|
94
|
+
|
95
|
+
* Switch `ruby2_keywords` gem from development dependency to runtime dependency
|
96
|
+
|
97
|
+
### 0.27.1
|
98
|
+
|
99
|
+
* Fix missing `ruby2_keywords` gem
|
100
|
+
* Allow passing string `offset` to `getbit` ([#203](https://github.com/sds/mock_redis/pull/203))
|
101
|
+
|
102
|
+
### 0.27.0
|
103
|
+
|
104
|
+
* Fix handling of keyword arguments on Ruby 3 ([#199](https://github.com/sds/mock_redis/pull/199))
|
105
|
+
* Allow passing string `offset` to `setbit` ([#200](https://github.com/sds/mock_redis/pull/200))
|
106
|
+
* Add `connection` method ([#201](https://github.com/sds/mock_redis/pull/201))
|
107
|
+
|
108
|
+
### 0.26.0
|
109
|
+
|
110
|
+
* Add block and count support to `xread` ([#194](https://github.com/sds/mock_redis/pull/194))
|
111
|
+
|
112
|
+
### 0.25.0
|
113
|
+
|
114
|
+
* Add support for `xread` command ([#190](https://github.com/sds/mock_redis/pull/190))
|
115
|
+
* Fix `mget` to raise error when passing empty array ([#191](https://github.com/sds/mock_redis/pull/191))
|
116
|
+
* Fix `xadd` when `maxlen` is zero ([#192](https://github.com/sds/mock_redis/pull/192))
|
117
|
+
|
118
|
+
### 0.24.0
|
119
|
+
|
120
|
+
* Fix handling of blocks within `multi` blocks ([#185](https://github.com/sds/mock_redis/pull/185))
|
121
|
+
* Fix handling of multiple consecutive `?` characters in key pattern matching ([#186](https://github.com/sds/mock_redis/pull/186))
|
122
|
+
* Change `exists` to return an integer and add `exists?` ([#188](https://github.com/sds/mock_redis/pull/188))
|
123
|
+
|
124
|
+
### 0.23.0
|
125
|
+
|
126
|
+
* Raise error when `setex` called with negative timeout ([#174](https://github.com/sds/mock_redis/pull/174))
|
127
|
+
* Add support for `dump`/`restore` between MockRedis instances ([#176](https://github.com/sds/mock_redis/pull/176))
|
128
|
+
* Fix warnings for ZSET methods on Ruby 2.7 ([#177](https://github.com/sds/mock_redis/pull/177))
|
129
|
+
* Add support for returning time in pipelines ([#179](https://github.com/sds/mock_redis/pull/179))
|
130
|
+
* Fix SET methods to correct set milliseconds with `px` ([#180](https://github.com/sds/mock_redis/pull/180))
|
131
|
+
* Add support for unsorted sets within `zinterstore`/`zunionstore`([#182](https://github.com/sds/mock_redis/pull/182))
|
132
|
+
|
133
|
+
### 0.22.0
|
134
|
+
|
135
|
+
* Gracefully handle cursors larger than the collection size in scan commands ([#171](https://github.com/sds/mock_redis/pull/171))
|
136
|
+
* Add `zpopmin` and `zpopmax` commands ([#172](https://github.com/sds/mock_redis/pull/172))
|
137
|
+
* Fix `hmset` to support array arguments ([#173](https://github.com/sds/mock_redis/pull/173))
|
138
|
+
* Fix `hmset` to always treat keys as strings ([#173](https://github.com/sds/mock_redis/pull/173))
|
139
|
+
* Remove unnecessary dependency on `rake` gem
|
140
|
+
|
141
|
+
### 0.21.0
|
142
|
+
|
143
|
+
* Fix behavior of `time` to return array of two integers ([#161](https://github.com/sds/mock_redis/pull/161))
|
144
|
+
* Add support for `close` and `disconnect!` ([#163](https://github.com/sds/mock_redis/pull/163))
|
145
|
+
* Fix `set` to properly handle (and ignore) other options ([#164](https://github.com/sds/mock_redis/pull/163))
|
146
|
+
* Fix `srem` to allow array of integers as argument ([#166](https://github.com/sds/mock_redis/pull/166))
|
147
|
+
* Fix `hdel` to allow array as argument ([#168](https://github.com/sds/mock_redis/pull/168))
|
148
|
+
|
149
|
+
### 0.20.0
|
150
|
+
|
151
|
+
* Add support for `count` parameter of `spop`
|
152
|
+
* Fix `mget` and `mset` to accept array as parameters
|
153
|
+
* Fix pipelined array replies
|
154
|
+
* Fix nested pipelining
|
155
|
+
* Allow nested multi
|
156
|
+
* Require Redis gem 4.0.1 or newer
|
157
|
+
* Add support for stream commands on Redis 5
|
158
|
+
* Keep empty strings on type mismatch
|
159
|
+
* Improve performance of `set_expiration`
|
160
|
+
* Fix `watch` to allow multiple keys
|
161
|
+
* Add `unlink` alias for `del`
|
162
|
+
* Drop support for Ruby 2.3 or older
|
163
|
+
|
3
164
|
### 0.19.0
|
4
165
|
|
5
166
|
* Require Ruby 2.2+
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MockRedis released under the MIT license.
|
2
|
+
|
3
|
+
> Copyright (c) Shane da Silva. http://shane.io
|
4
|
+
>
|
5
|
+
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
> of this software and associated documentation files (the "Software"), to deal
|
7
|
+
> in the Software without restriction, including without limitation the rights
|
8
|
+
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
> copies of the Software, and to permit persons to whom the Software is
|
10
|
+
> furnished to do so, subject to the following conditions:
|
11
|
+
>
|
12
|
+
> The above copyright notice and this permission notice shall be included in
|
13
|
+
> all copies or substantial portions of the Software.
|
14
|
+
>
|
15
|
+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
> SOFTWARE.
|
data/README.md
CHANGED
@@ -1,18 +1,27 @@
|
|
1
1
|
# MockRedis
|
2
2
|
|
3
3
|
[](http://badge.fury.io/rb/mock_redis)
|
4
|
-
|
5
|
-
[
|
5
|
+
[](https://coveralls.io/r/sds/mock_redis)
|
6
6
|
|
7
7
|
MockRedis provides the same interface as `redis-rb`, but it stores its
|
8
8
|
data in memory instead of talking to a Redis server. It is intended
|
9
9
|
for use in tests.
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
## Requirements
|
12
|
+
|
13
|
+
Ruby 3.0+
|
14
|
+
|
15
|
+
The current implementation is tested against Redis 6.2. Older versions may work, but can also return different results or not support some commands.
|
13
16
|
|
14
17
|
## Getting Started
|
15
18
|
|
19
|
+
Install the gem:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
gem install mock_redis
|
23
|
+
```
|
24
|
+
|
16
25
|
It's as easy as `require 'mock_redis'; mr = MockRedis.new`. Then you can
|
17
26
|
call the same methods on it as you can call on a real `Redis` object.
|
18
27
|
|
@@ -46,8 +55,8 @@ since it's an in-memory object confined to a single process. MockRedis
|
|
46
55
|
makes every attempt to be Redis-compatible, but there are some
|
47
56
|
necessary exceptions.
|
48
57
|
|
49
|
-
* Blocking list commands (`#blpop`, `#brpop`, and `#brpoplpush`)
|
50
|
-
as expected if there is data for them to retrieve. If you use one of
|
58
|
+
* Blocking list commands (`#blmove`, `#blpop`, `#brpop`, and `#brpoplpush`)
|
59
|
+
work as expected if there is data for them to retrieve. If you use one of
|
51
60
|
these commands with a nonzero timeout and there is no data for it to
|
52
61
|
retrieve, then the command returns immediately. However, if you ask
|
53
62
|
one of these commands for data with a 0 timeout (means "wait
|
@@ -90,17 +99,32 @@ please submit a pull request with your (tested!) implementation.
|
|
90
99
|
* `#config(:get|:set|:resetstat)` isn't done. They can just return
|
91
100
|
canned values.
|
92
101
|
|
93
|
-
##
|
102
|
+
## Running tests
|
103
|
+
|
104
|
+
We recommend running Redis within a Docker container to make development as simple as possible, but as long as you have a Redis instance listening on `localhost:6379` you should be good to go.
|
105
|
+
|
106
|
+
1. Start Redis.
|
107
|
+
```bash
|
108
|
+
docker run --rm -p 6379:6379 redis:6.2-alpine
|
109
|
+
```
|
110
|
+
2. Install dependencies.
|
111
|
+
```bash
|
112
|
+
bundle install
|
113
|
+
```
|
114
|
+
3. Run tests.
|
115
|
+
```bash
|
116
|
+
bundle exec rspec
|
117
|
+
```
|
118
|
+
|
119
|
+
These tests were written with Redis running on `localhost` without any
|
120
|
+
passwords required. If you're using a different version of Redis, you
|
121
|
+
may see failures due to error message text being different and other
|
122
|
+
breaking changes over time.
|
123
|
+
|
124
|
+
## Changelog
|
94
125
|
|
95
|
-
|
96
|
-
older versions of Ruby, use `0.18.0` or older.
|
126
|
+
If you're interested in seeing the changes and bug fixes between each version of `mock_redis`, read the [MockRedis Changelog](CHANGELOG.md).
|
97
127
|
|
98
|
-
##
|
128
|
+
## License
|
99
129
|
|
100
|
-
|
101
|
-
tests. (Just kidding! There's no probably about it.) These tests were
|
102
|
-
written with Redis running on `localhost` without any passwords
|
103
|
-
required. If you're using a different version of Redis, you may see
|
104
|
-
failures due to error message text being different. If you're running
|
105
|
-
a really old version of Redis, you'll definitely see failures due to
|
106
|
-
stuff that doesn't work!
|
130
|
+
This project is released under the [MIT license](LICENSE.md).
|
data/lib/mock_redis/database.rb
CHANGED
@@ -10,6 +10,9 @@ require 'mock_redis/indifferent_hash'
|
|
10
10
|
require 'mock_redis/info_method'
|
11
11
|
require 'mock_redis/utility_methods'
|
12
12
|
require 'mock_redis/geospatial_methods'
|
13
|
+
require 'mock_redis/stream_methods'
|
14
|
+
require 'mock_redis/connection_method'
|
15
|
+
require 'mock_redis/memory_method'
|
13
16
|
|
14
17
|
class MockRedis
|
15
18
|
class Database
|
@@ -22,6 +25,9 @@ class MockRedis
|
|
22
25
|
include InfoMethod
|
23
26
|
include UtilityMethods
|
24
27
|
include GeospatialMethods
|
28
|
+
include StreamMethods
|
29
|
+
include ConnectionMethod
|
30
|
+
include MemoryMethod
|
25
31
|
|
26
32
|
attr_reader :data, :expire_times
|
27
33
|
|
@@ -33,12 +39,19 @@ class MockRedis
|
|
33
39
|
|
34
40
|
def initialize_copy(_source)
|
35
41
|
@data = @data.clone
|
36
|
-
@data.
|
42
|
+
@data.each_key { |k| @data[k] = @data[k].clone }
|
37
43
|
@expire_times = @expire_times.map(&:clone)
|
38
44
|
end
|
39
45
|
|
40
46
|
# Redis commands go below this line and above 'private'
|
41
47
|
|
48
|
+
# FIXME: Current implementation of `call` does not work propetly with kwarg-options.
|
49
|
+
# i.e. `call("EXPIRE", "foo", 40, "NX")` (which redis-rb will simply transmit to redis-server)
|
50
|
+
# will be passed to `#expire` without keywords transformation.
|
51
|
+
def call(command, &_block)
|
52
|
+
public_send(command[0].downcase, *command[1..])
|
53
|
+
end
|
54
|
+
|
42
55
|
def auth(_)
|
43
56
|
'OK'
|
44
57
|
end
|
@@ -54,6 +67,8 @@ class MockRedis
|
|
54
67
|
def disconnect
|
55
68
|
nil
|
56
69
|
end
|
70
|
+
alias close disconnect
|
71
|
+
alias disconnect! close
|
57
72
|
|
58
73
|
def connected?
|
59
74
|
true
|
@@ -65,7 +80,7 @@ class MockRedis
|
|
65
80
|
|
66
81
|
def del(*keys)
|
67
82
|
keys = keys.flatten.map(&:to_s)
|
68
|
-
assert_has_args(keys, 'del')
|
83
|
+
# assert_has_args(keys, 'del') # no longer errors in redis > v4.5
|
69
84
|
|
70
85
|
keys.
|
71
86
|
find_all { |key| data[key] }.
|
@@ -73,48 +88,81 @@ class MockRedis
|
|
73
88
|
each { |k| data.delete(k) }.
|
74
89
|
length
|
75
90
|
end
|
91
|
+
alias unlink del
|
76
92
|
|
77
93
|
def echo(msg)
|
78
94
|
msg.to_s
|
79
95
|
end
|
80
96
|
|
81
|
-
def expire(key, seconds)
|
82
|
-
|
97
|
+
def expire(key, seconds, nx: nil, xx: nil, lt: nil, gt: nil) # rubocop:disable Metrics/ParameterLists
|
98
|
+
assert_valid_integer(seconds)
|
99
|
+
|
100
|
+
pexpire(key, seconds.to_i * 1000, nx: nx, xx: xx, lt: lt, gt: gt)
|
83
101
|
end
|
84
102
|
|
85
|
-
def pexpire(key, ms)
|
86
|
-
|
87
|
-
|
103
|
+
def pexpire(key, ms, nx: nil, xx: nil, lt: nil, gt: nil) # rubocop:disable Metrics/ParameterLists
|
104
|
+
assert_valid_integer(ms)
|
105
|
+
|
106
|
+
now, miliseconds = @base.now
|
107
|
+
now_ms = (now * 1000) + miliseconds
|
108
|
+
pexpireat(key, now_ms + ms.to_i, nx: nx, xx: xx, lt: lt, gt: gt)
|
88
109
|
end
|
89
110
|
|
90
|
-
def expireat(key, timestamp)
|
91
|
-
|
92
|
-
raise Redis::CommandError, 'ERR value is not an integer or out of range'
|
93
|
-
end
|
111
|
+
def expireat(key, timestamp, nx: nil, xx: nil, lt: nil, gt: nil) # rubocop:disable Metrics/ParameterLists
|
112
|
+
assert_valid_integer(timestamp)
|
94
113
|
|
95
|
-
pexpireat(key, timestamp.to_i * 1000)
|
114
|
+
pexpireat(key, timestamp.to_i * 1000, nx: nx, xx: xx, lt: lt, gt: gt)
|
96
115
|
end
|
97
116
|
|
98
|
-
def pexpireat(key, timestamp_ms)
|
99
|
-
|
100
|
-
|
117
|
+
def pexpireat(key, timestamp_ms, nx: nil, xx: nil, lt: nil, gt: nil) # rubocop:disable Metrics/ParameterLists
|
118
|
+
assert_valid_integer(timestamp_ms)
|
119
|
+
|
120
|
+
if nx && gt || gt && lt || lt && nx || nx && xx
|
121
|
+
raise Redis::CommandError, <<~TXT.chomp
|
122
|
+
ERR NX and XX, GT or LT options at the same time are not compatible
|
123
|
+
TXT
|
101
124
|
end
|
102
125
|
|
103
|
-
|
104
|
-
|
105
|
-
|
126
|
+
return false unless exists?(key)
|
127
|
+
|
128
|
+
expiry = expiration(key)
|
129
|
+
new_expiry = @base.time_at(Rational(timestamp_ms.to_i, 1000))
|
130
|
+
|
131
|
+
if should_update_expiration?(expiry, new_expiry, nx: nx, xx: xx, lt: lt, gt: gt)
|
132
|
+
set_expiration(key, new_expiry)
|
106
133
|
true
|
107
134
|
else
|
108
135
|
false
|
109
136
|
end
|
110
137
|
end
|
111
138
|
|
112
|
-
def exists(
|
113
|
-
data.key?(key)
|
139
|
+
def exists(*keys)
|
140
|
+
keys.count { |key| data.key?(key) }
|
141
|
+
end
|
142
|
+
|
143
|
+
def exists?(*keys)
|
144
|
+
keys.each { |key| return true if data.key?(key) }
|
145
|
+
false
|
114
146
|
end
|
115
147
|
|
116
148
|
def flushdb
|
117
|
-
data.
|
149
|
+
data.each_key { |k| del(k) }
|
150
|
+
'OK'
|
151
|
+
end
|
152
|
+
|
153
|
+
def dump(key)
|
154
|
+
value = data[key]
|
155
|
+
value ? Marshal.dump(value) : nil
|
156
|
+
end
|
157
|
+
|
158
|
+
def restore(key, ttl, value, replace: false)
|
159
|
+
if !replace && exists?(key)
|
160
|
+
raise Redis::CommandError, 'BUSYKEY Target key name already exists.'
|
161
|
+
end
|
162
|
+
data[key] = Marshal.load(value) # rubocop:disable Security/MarshalLoad
|
163
|
+
if ttl > 0
|
164
|
+
pexpire(key, ttl)
|
165
|
+
end
|
118
166
|
'OK'
|
119
167
|
end
|
120
168
|
|
@@ -137,11 +185,11 @@ class MockRedis
|
|
137
185
|
end
|
138
186
|
|
139
187
|
def lastsave
|
140
|
-
|
188
|
+
now.first
|
141
189
|
end
|
142
190
|
|
143
191
|
def persist(key)
|
144
|
-
if exists(key) && has_expiration?(key)
|
192
|
+
if exists?(key) && has_expiration?(key)
|
145
193
|
remove_expiration(key)
|
146
194
|
true
|
147
195
|
else
|
@@ -149,8 +197,8 @@ class MockRedis
|
|
149
197
|
end
|
150
198
|
end
|
151
199
|
|
152
|
-
def ping
|
153
|
-
|
200
|
+
def ping(response = 'PONG')
|
201
|
+
response
|
154
202
|
end
|
155
203
|
|
156
204
|
def quit
|
@@ -182,7 +230,7 @@ class MockRedis
|
|
182
230
|
raise Redis::CommandError, 'ERR no such key'
|
183
231
|
end
|
184
232
|
|
185
|
-
if exists(newkey)
|
233
|
+
if exists?(newkey)
|
186
234
|
false
|
187
235
|
else
|
188
236
|
rename(key, newkey)
|
@@ -195,27 +243,38 @@ class MockRedis
|
|
195
243
|
end
|
196
244
|
|
197
245
|
def ttl(key)
|
198
|
-
if !exists(key)
|
246
|
+
if !exists?(key)
|
199
247
|
-2
|
200
248
|
elsif has_expiration?(key)
|
201
|
-
|
249
|
+
now, = @base.now
|
250
|
+
expiration(key).to_i - now
|
202
251
|
else
|
203
252
|
-1
|
204
253
|
end
|
205
254
|
end
|
206
255
|
|
207
256
|
def pttl(key)
|
208
|
-
|
257
|
+
now, miliseconds = @base.now
|
258
|
+
now_ms = now * 1000 + miliseconds
|
259
|
+
|
260
|
+
if !exists?(key)
|
209
261
|
-2
|
210
262
|
elsif has_expiration?(key)
|
211
|
-
(expiration(key).to_r * 1000).to_i -
|
263
|
+
(expiration(key).to_r * 1000).to_i - now_ms
|
212
264
|
else
|
213
265
|
-1
|
214
266
|
end
|
215
267
|
end
|
216
268
|
|
269
|
+
def now
|
270
|
+
current_time = @base.options[:time_class].now
|
271
|
+
miliseconds = (current_time.to_r - current_time.to_i) * 1_000
|
272
|
+
[current_time.to_i, miliseconds.to_i]
|
273
|
+
end
|
274
|
+
alias time now
|
275
|
+
|
217
276
|
def type(key)
|
218
|
-
if !exists(key)
|
277
|
+
if !exists?(key)
|
219
278
|
'none'
|
220
279
|
elsif hashy?(key)
|
221
280
|
'hash'
|
@@ -227,6 +286,8 @@ class MockRedis
|
|
227
286
|
'set'
|
228
287
|
elsif zsety?(key)
|
229
288
|
'zset'
|
289
|
+
elsif streamy?(key)
|
290
|
+
'stream'
|
230
291
|
else
|
231
292
|
raise ArgumentError, "Not sure how #{data[key].inspect} got in here"
|
232
293
|
end
|
@@ -240,6 +301,13 @@ class MockRedis
|
|
240
301
|
|
241
302
|
private
|
242
303
|
|
304
|
+
def assert_valid_integer(integer)
|
305
|
+
unless looks_like_integer?(integer.to_s)
|
306
|
+
raise Redis::CommandError, 'ERR value is not an integer or out of range'
|
307
|
+
end
|
308
|
+
integer
|
309
|
+
end
|
310
|
+
|
243
311
|
def assert_valid_timeout(timeout)
|
244
312
|
if !looks_like_integer?(timeout.to_s)
|
245
313
|
raise Redis::CommandError, 'ERR timeout is not an integer or out of range'
|
@@ -271,7 +339,7 @@ class MockRedis
|
|
271
339
|
end
|
272
340
|
|
273
341
|
def expiration(key)
|
274
|
-
expire_times.find { |(_, k)| k == key.to_s }
|
342
|
+
expire_times.find { |(_, k)| k == key.to_s }&.first
|
275
343
|
end
|
276
344
|
|
277
345
|
def has_expiration?(key)
|
@@ -286,11 +354,19 @@ class MockRedis
|
|
286
354
|
!!Float(str) rescue false
|
287
355
|
end
|
288
356
|
|
357
|
+
def should_update_expiration?(expiry, new_expiry, nx:, xx:, lt:, gt:) # rubocop:disable Metrics/ParameterLists
|
358
|
+
return false if nx && expiry || xx && !expiry
|
359
|
+
return false if lt && expiry && new_expiry > expiry
|
360
|
+
return false if gt && (!expiry || new_expiry < expiry)
|
361
|
+
|
362
|
+
true
|
363
|
+
end
|
364
|
+
|
289
365
|
def redis_pattern_to_ruby_regex(pattern)
|
290
366
|
Regexp.new(
|
291
367
|
"^#{pattern}$".
|
292
|
-
gsub(/([+|()])/, '\\\\\1').
|
293
|
-
gsub(/(
|
368
|
+
gsub(/([+|(){}])/, '\\\\\1').
|
369
|
+
gsub(/(?<!\\)\?/, '\\1.').
|
294
370
|
gsub(/([^\\])\*/, '\\1.*')
|
295
371
|
)
|
296
372
|
end
|
@@ -303,11 +379,9 @@ class MockRedis
|
|
303
379
|
|
304
380
|
def set_expiration(key, time)
|
305
381
|
remove_expiration(key)
|
306
|
-
|
307
|
-
|
308
|
-
expire_times.
|
309
|
-
a.first <=> b.first
|
310
|
-
end
|
382
|
+
found = expire_times.each_with_index.to_a.bsearch { |item, _| item.first >= time }
|
383
|
+
index = found ? found.last : -1
|
384
|
+
expire_times.insert(index, [time, key.to_s])
|
311
385
|
end
|
312
386
|
|
313
387
|
def zero_pad(string, desired_length)
|
@@ -320,10 +394,11 @@ class MockRedis
|
|
320
394
|
# This method isn't private, but it also isn't a Redis command, so
|
321
395
|
# it doesn't belong up above with all the Redis commands.
|
322
396
|
def expire_keys
|
323
|
-
|
397
|
+
now_sec, miliseconds = now
|
398
|
+
now_ms = now_sec * 1_000 + miliseconds
|
324
399
|
|
325
400
|
to_delete = expire_times.take_while do |(time, _key)|
|
326
|
-
(time.to_r * 1_000).to_i <=
|
401
|
+
(time.to_r * 1_000).to_i <= now_ms
|
327
402
|
end
|
328
403
|
|
329
404
|
to_delete.each do |(_time, key)|
|