mock_redis 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4443d90955b31a149afd0c66972a06993bf9b01f6bd826276c2d60edb49b3141
4
- data.tar.gz: 2d096c0b7438b81720adcd50ecb36a8fa19df7a05c822ed4beee6d06d459f1b4
3
+ metadata.gz: d9dd8cc0a4f19edccfb6c7b3f1a82724f0da757ad7139f4a576eed1d0b815b8d
4
+ data.tar.gz: 980f4326447c75afb034b6292baab71bb723ca05689b04aa7ed4933bd8bbf356
5
5
  SHA512:
6
- metadata.gz: bdcb30c9756e77fcc4f857f0bdaa01d73faa28b8ea7cc37aa669c0f5cf2e2967d3e216a32ff50c7c78f6945b313f8525073060daf9f980187d566202f3dbcda2
7
- data.tar.gz: 17502b628f1a5a62fa2046b529ef0178d8b84453d3a8b83441e3f2eef72282d45a79e60bee34e9a871ea553deb08c1c286b915d4b2c6ffe52fab3e6e32a6cc56
6
+ metadata.gz: 53a8419ef9f62a4d276993714241f22f9da4087df9ce69158821ea42c735e4fc022f4ab9431bbef268eb562130cc139308fd46ad9eeef8941ef95d9b56afc083
7
+ data.tar.gz: 266de40ac11c22fa449d709380cec9461a93cd18c6950d31aee538b295c613ab2a0ee2fb828420ff02ea2e2351e92e2d565a9bad630abfd21abf8b8eab7c144d
@@ -17,9 +17,9 @@ before_install:
17
17
  - echo PING | nc localhost 6379
18
18
 
19
19
  rvm:
20
- - 2.4.6
21
- - 2.5.5
22
- - 2.6.3
20
+ - 2.4
21
+ - 2.5
22
+ - 2.6
23
23
 
24
24
  before_script:
25
25
  - git config --local user.email "travis@travis.ci"
@@ -1,5 +1,13 @@
1
1
  # MockRedis Changelog
2
2
 
3
+ ### 0.22.0
4
+
5
+ * Gracefully handle cursors larger than the collection size in scan commands ([#171](https://github.com/sds/mock_redis/pull/171))
6
+ * Add `zpopmin` and `zpopmax` commands ([#172](https://github.com/sds/mock_redis/pull/172))
7
+ * Fix `hmset` to support array arguments ([#173](https://github.com/sds/mock_redis/pull/173))
8
+ * Fix `hmset` to always treat keys as strings ([#173](https://github.com/sds/mock_redis/pull/173))
9
+ * Remove unnecessary dependency on `rake` gem
10
+
3
11
  ### 0.21.0
4
12
 
5
13
  * Fix behavior of `time` to return array of two integers ([#161](https://github.com/sds/mock_redis/pull/161))
@@ -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
@@ -8,11 +8,20 @@ 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
- The current implementation is tested against *Redis 4*. Older versions
12
- of Redis may return different results or not support some commands.
11
+ ## Requirements
12
+
13
+ * Ruby 2.4+
14
+
15
+ The current implementation is tested against **Redis 5**. 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
 
@@ -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
- ## Compatibility
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
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
- As of version `0.19.0`, Ruby 2.2 and above are supported. For
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
- ## Running the Tests
128
+ ## License
99
129
 
100
- If you want to work on this, you'll probably want to run the
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).
@@ -84,10 +84,17 @@ class MockRedis
84
84
  end
85
85
 
86
86
  def hmset(key, *kvpairs)
87
+ if key.is_a? Array
88
+ err_msg = 'ERR wrong number of arguments for \'hmset\' command'
89
+ kvpairs = key[1..-1]
90
+ key = key[0]
91
+ end
92
+
87
93
  kvpairs.flatten!
88
94
  assert_has_args(kvpairs, 'hmset')
95
+
89
96
  if kvpairs.length.odd?
90
- raise Redis::CommandError, 'ERR wrong number of arguments for HMSET'
97
+ raise Redis::CommandError, err_msg || 'ERR wrong number of arguments for HMSET'
91
98
  end
92
99
 
93
100
  kvpairs.each_slice(2) do |(k, v)|
@@ -143,7 +150,7 @@ class MockRedis
143
150
  private
144
151
 
145
152
  def with_hash_at(key, &blk)
146
- with_thing_at(key, :assert_hashy, proc { {} }, &blk)
153
+ with_thing_at(key.to_s, :assert_hashy, proc { {} }, &blk)
147
154
  end
148
155
 
149
156
  def hashy?(key)
@@ -28,12 +28,15 @@ class MockRedis
28
28
  cursor = cursor.to_i
29
29
  match = opts[:match] || '*'
30
30
  key = opts[:key] || lambda { |x| x }
31
+ filtered_values = []
31
32
 
32
33
  limit = cursor + count
33
34
  next_cursor = limit >= values.length ? '0' : limit.to_s
34
35
 
35
- filtered_values = values[cursor...limit].select do |val|
36
- redis_pattern_to_ruby_regex(match).match(key.call(val))
36
+ unless values[cursor...limit].nil?
37
+ filtered_values = values[cursor...limit].select do |val|
38
+ redis_pattern_to_ruby_regex(match).match(key.call(val))
39
+ end
37
40
  end
38
41
 
39
42
  [next_cursor, filtered_values]
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Defines the gem version.
4
4
  class MockRedis
5
- VERSION = '0.21.0'
5
+ VERSION = '0.22.0'
6
6
  end
@@ -155,6 +155,24 @@ class MockRedis
155
155
  retval
156
156
  end
157
157
 
158
+ def zpopmin(key, count = 1)
159
+ with_zset_at(key) do |z|
160
+ pairs = z.sorted.first(count)
161
+ pairs.each { |pair| z.delete?(pair.last) }
162
+ retval = to_response(pairs, with_scores: true)
163
+ count == 1 ? retval.first : retval
164
+ end
165
+ end
166
+
167
+ def zpopmax(key, count = 1)
168
+ with_zset_at(key) do |z|
169
+ pairs = z.sorted.reverse.first(count)
170
+ pairs.each { |pair| z.delete?(pair.last) }
171
+ retval = to_response(pairs, with_scores: true)
172
+ count == 1 ? retval.first : retval
173
+ end
174
+ end
175
+
158
176
  def zrevrange(key, start, stop, options = {})
159
177
  with_zset_at(key) do |z|
160
178
  to_response(z.sorted.reverse[start..stop] || [], options)
@@ -23,8 +23,7 @@ Gem::Specification.new do |s|
23
23
 
24
24
  s.required_ruby_version = '>= 2.4'
25
25
 
26
- s.add_development_dependency 'rake', '>= 10', '< 12'
27
- s.add_development_dependency 'redis', '~>4.1.0'
26
+ s.add_development_dependency 'redis', '~> 4.1.0'
28
27
  s.add_development_dependency 'rspec', '~> 3.0'
29
28
  s.add_development_dependency 'rspec-its', '~> 1.0'
30
29
  s.add_development_dependency 'timecop', '~> 0.9.1'
@@ -39,5 +39,31 @@ describe '#hmset(key, field, value [, field, value ...])' do
39
39
  end.should raise_error(Redis::CommandError)
40
40
  end
41
41
 
42
+ # The following tests address https://github.com/sds/mock_redis/issues/170
43
+ context 'keys are stored as strings' do
44
+ before do
45
+ @redises.hmset(1, :foo, :bar)
46
+ @redises.hmset(:a_sym, :boo, :bas)
47
+ end
48
+
49
+ it { expect(@redises.hgetall('1')).to eq @redises.hgetall(1) }
50
+ it { expect(@redises.hgetall('a_sym')).to eq @redises.hgetall(:a_sym) }
51
+ it { expect(@redises.del('1')).to eq 1 }
52
+ it { expect(@redises.del(1)).to eq 1 }
53
+ it { expect(@redises.del('a_sym')).to eq 1 }
54
+ it { expect(@redises.del(:a_sym)).to eq 1 }
55
+
56
+ after do
57
+ @redises.del(1)
58
+ @redises.del(:a_sym)
59
+ end
60
+ end
61
+
62
+ # The following tests address https://github.com/sds/mock_redis/issues/134
63
+ context 'hmset accepts an array as its only argument' do
64
+ it { expect(@redises.hmset([@key, :bar, :bas])).to eq 'OK' }
65
+ it { lambda { @redises.hmset([:foo, :bar]) }.should raise_error(Redis::CommandError) }
66
+ end
67
+
42
68
  it_should_behave_like 'a hash-only command'
43
69
  end
@@ -42,6 +42,15 @@ describe '#scan' do
42
42
  end
43
43
  end
44
44
 
45
+ context 'when cursor is greater than collection size' do
46
+ let(:collection) { Array.new(count) { |i| "mock:key#{i}" } }
47
+ let(:expected) { ['0', []] }
48
+
49
+ it 'returns a 0 cursor and empty collection' do
50
+ expect(subject.scan(20, count: count, match: match)).to eq(expected)
51
+ end
52
+ end
53
+
45
54
  context 'when giving a custom match filter' do
46
55
  let(:match) { 'mock:key*' }
47
56
  let(:collection) { %w[mock:key mock:key2 mock:otherkey] }
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#zpopmax(key, count)' do
4
+ before(:each) do
5
+ @key = 'mock-redis-test:zpopmax'
6
+ @redises.del(@key)
7
+ @redises.zadd(@key, 1, 'one')
8
+ @redises.zadd(@key, 2, 'two')
9
+ @redises.zadd(@key, 3, 'three')
10
+ end
11
+
12
+ context 'when count is unspecified' do
13
+ it 'returns nil if the set does not exist' do
14
+ @redises.zpopmax('does-not-exist').should nil
15
+ end
16
+
17
+ it 'returns the highest ranked element' do
18
+ @redises.zpopmax(@key).should == ['three', 3]
19
+ @redises.zcard(@key).should == 2
20
+ end
21
+ end
22
+
23
+ context 'when count is 1' do
24
+ let(:count) { 1 }
25
+
26
+ it 'returns nil if the set does not exist' do
27
+ @redises.zpopmax('does-not-exist', count).should nil
28
+ end
29
+
30
+ it 'returns the highest ranked element' do
31
+ @redises.zpopmax(@key, count).should == ['three', 3]
32
+ @redises.zcard(@key).should == 2
33
+ end
34
+ end
35
+
36
+ context 'when count is greater than 1' do
37
+ let(:count) { 2 }
38
+
39
+ it 'returns empty array if the set does not exist' do
40
+ @redises.zpopmax('does-not-exist', count).should == []
41
+ end
42
+
43
+ it 'returns the highest ranked elements' do
44
+ @redises.zpopmax(@key, count).should == [['three', 3], ['two', 2]]
45
+ @redises.zcard(@key).should == 1
46
+ end
47
+ end
48
+
49
+ context 'when count is greater than the size of the set' do
50
+ let(:count) { 4 }
51
+
52
+ it 'returns the entire set' do
53
+ before = @redises.zrange(@key, 0, count, with_scores: true).reverse
54
+ @redises.zpopmax(@key, count).should == before
55
+ @redises.zcard(@key).should == 0
56
+ end
57
+ end
58
+
59
+ it_should_behave_like 'a zset-only command'
60
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#zpopmin(key, count)' do
4
+ before(:each) do
5
+ @key = 'mock-redis-test:zpopmin'
6
+ @redises.del(@key)
7
+ @redises.zadd(@key, 1, 'one')
8
+ @redises.zadd(@key, 2, 'two')
9
+ @redises.zadd(@key, 3, 'three')
10
+ end
11
+
12
+ context 'when count is unspecified' do
13
+ it 'returns nil if the set does not exist' do
14
+ @redises.zpopmin('does-not-exist').should nil
15
+ end
16
+
17
+ it 'returns the lowest ranked element' do
18
+ @redises.zpopmin(@key).should == ['one', 1]
19
+ @redises.zcard(@key).should == 2
20
+ end
21
+ end
22
+
23
+ context 'when count is 1' do
24
+ let(:count) { 1 }
25
+
26
+ it 'returns nil if the set does not exist' do
27
+ @redises.zpopmin('does-not-exist', count).should nil
28
+ end
29
+
30
+ it 'returns the lowest ranked element' do
31
+ @redises.zpopmin(@key, count).should == ['one', 1]
32
+ @redises.zcard(@key).should == 2
33
+ end
34
+ end
35
+
36
+ context 'when count is greater than 1' do
37
+ let(:count) { 2 }
38
+
39
+ it 'returns empty array if the set does not exist' do
40
+ @redises.zpopmin('does-not-exist', count).should == []
41
+ end
42
+
43
+ it 'returns the lowest ranked elements' do
44
+ @redises.zpopmin(@key, count).should == [['one', 1], ['two', 2]]
45
+ @redises.zcard(@key).should == 1
46
+ end
47
+ end
48
+
49
+ context 'when count is greater than the size of the set' do
50
+ let(:count) { 4 }
51
+
52
+ it 'returns the entire set' do
53
+ before = @redises.zrange(@key, 0, count, with_scores: true)
54
+ @redises.zpopmin(@key, count).should == before
55
+ @redises.zcard(@key).should == 0
56
+ end
57
+ end
58
+
59
+ it_should_behave_like 'a zset-only command'
60
+ end
@@ -27,7 +27,7 @@ module TypeCheckingHelper
27
27
  end
28
28
 
29
29
  def args_for_method(method)
30
- return [] if method.to_s == 'spop'
30
+ return [] if %w[spop zpopmin zpopmax].include?(method.to_s)
31
31
  method_arity = @redises.real.method(method).arity
32
32
  if method_arity < 0 # -1 comes from def foo(*args)
33
33
  [1, 2] # probably good enough
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mock_redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane da Silva
@@ -9,28 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-06-26 00:00:00.000000000 Z
12
+ date: 2019-10-10 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: rake
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: '10'
21
- - - "<"
22
- - !ruby/object:Gem::Version
23
- version: '12'
24
- type: :development
25
- prerelease: false
26
- version_requirements: !ruby/object:Gem::Requirement
27
- requirements:
28
- - - ">="
29
- - !ruby/object:Gem::Version
30
- version: '10'
31
- - - "<"
32
- - !ruby/object:Gem::Version
33
- version: '12'
34
14
  - !ruby/object:Gem::Dependency
35
15
  name: redis
36
16
  requirement: !ruby/object:Gem::Requirement
@@ -105,7 +85,7 @@ files:
105
85
  - ".travis.yml"
106
86
  - CHANGELOG.md
107
87
  - Gemfile
108
- - LICENSE
88
+ - LICENSE.md
109
89
  - README.md
110
90
  - Rakefile
111
91
  - lib/mock_redis.rb
@@ -266,6 +246,8 @@ files:
266
246
  - spec/commands/zcount_spec.rb
267
247
  - spec/commands/zincrby_spec.rb
268
248
  - spec/commands/zinterstore_spec.rb
249
+ - spec/commands/zpopmax_spec.rb
250
+ - spec/commands/zpopmin_spec.rb
269
251
  - spec/commands/zrange_spec.rb
270
252
  - spec/commands/zrangebyscore_spec.rb
271
253
  - spec/commands/zrank_spec.rb
@@ -446,6 +428,8 @@ test_files:
446
428
  - spec/commands/zcount_spec.rb
447
429
  - spec/commands/zincrby_spec.rb
448
430
  - spec/commands/zinterstore_spec.rb
431
+ - spec/commands/zpopmax_spec.rb
432
+ - spec/commands/zpopmin_spec.rb
449
433
  - spec/commands/zrange_spec.rb
450
434
  - spec/commands/zrangebyscore_spec.rb
451
435
  - spec/commands/zrank_spec.rb
data/LICENSE DELETED
@@ -1,19 +0,0 @@
1
- Copyright (c) 2011 Philotic, Inc.
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy
4
- of this software and associated documentation files (the "Software"), to deal
5
- in the Software without restriction, including without limitation the rights
6
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- copies of the Software, and to permit persons to whom the Software is
8
- furnished to do so, subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in
11
- all copies or substantial portions of the Software.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- THE SOFTWARE.