mock_redis 0.15.4 → 0.16.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
  SHA1:
3
- metadata.gz: 067542610c0d8223c9b08324c9855c036e1fe199
4
- data.tar.gz: 4c79481ce9e4404063cda484fa8d74709d5e9171
3
+ metadata.gz: cfac83d82686c7ae7355880b0ecc9263b44f0b2a
4
+ data.tar.gz: 65edf9e01b7cdc5da7f02bc88cf4703b12d4e043
5
5
  SHA512:
6
- metadata.gz: a14d2235b776964f5fc38ecbb77ac27c125d4436e405c4cd093697272c103c6ca934e86099053fd2be943f6cbc69d8f8cd6a01a3239080be9d5b1b747b98b402
7
- data.tar.gz: 963c9b2b60490745a4b905a012ba6131a18b8fade75b04c0c7c5e8efa3592951e27c48c6ccf97ab47f0a1c7bd6cc6f8abf8450f890d5c537eb5e0882b589e070
6
+ metadata.gz: d6e80d56dfcbad007f71b0c58f1de1f056592880f0d10516224f3d91e0e1ef3bfb405d4b5a482668146bfee978d8c7a4307ee25951960ebd18a8d9d19c0eff0a
7
+ data.tar.gz: 43900cd389c65597930932a4c95de2469909131396840a2a693ddbe77b7dbae024546c21dfae487e2b73c5fb8fa3e568b58af6503f1c7e18a24f8a0888fb76a7
@@ -83,9 +83,10 @@ Style/SignalException:
83
83
  Style/SingleLineBlockParams:
84
84
  Enabled: false
85
85
 
86
- # Disabled since as of RuboCop 0.35.1 it reports false positives for trailing
87
- # commas in lists with a single item
88
- Style/TrailingComma:
86
+ Style/TrailingCommaInArguments:
87
+ Enabled: false
88
+
89
+ Style/TrailingCommaInLiteral:
89
90
  Enabled: false
90
91
 
91
92
  Style/WhenThen:
@@ -12,6 +12,7 @@ rvm:
12
12
  - 2.0
13
13
  - 2.1
14
14
  - 2.2
15
+ - 2.3.0
15
16
  - jruby-19mode
16
17
 
17
18
  before_script:
@@ -20,6 +21,7 @@ before_script:
20
21
 
21
22
  script:
22
23
  - bundle exec rspec
24
+ - bundle exec overcommit --sign
23
25
  - bundle exec overcommit --run
24
26
 
25
27
  matrix:
@@ -1,5 +1,11 @@
1
1
  # MockRedis Changelog
2
2
 
3
+ ### 0.16.0
4
+
5
+ * Add stub implementations for `script`/`eval`/`evalsha` commands
6
+ * Add implementations for `SCAN` family (`sscan`/`hscan`/`zscan`)
7
+ family of commands
8
+
3
9
  ### 0.15.4
4
10
 
5
11
  * Fix `zrange`/`zrevrange` to return elements with equal values in
data/Gemfile CHANGED
@@ -4,10 +4,10 @@ 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.28.0'
7
+ gem 'overcommit', '0.30.0'
8
8
 
9
9
  # Pin tool versions (which are executed by Overcommit) for Travis builds
10
- gem 'rubocop', '0.35.1'
10
+ gem 'rubocop', '0.36.0'
11
11
  gem 'travis', '~> 1.7'
12
12
 
13
13
  gem 'coveralls', require: false
data/README.md CHANGED
@@ -80,6 +80,8 @@ Ruby process.
80
80
 
81
81
  * `#slowlog` isn't available.
82
82
 
83
+ * Scripting commands (`#script`, `#eval`, `#evalsha`) are just stubs—they won't execute anything
84
+
83
85
  ## Remaining Work
84
86
 
85
87
  There are some things we want to have in here, but that we just
@@ -23,7 +23,7 @@ class MockRedis
23
23
  :password => nil,
24
24
  :db => 0,
25
25
  :time_class => Time,
26
- }
26
+ }.freeze
27
27
 
28
28
  def self.connect(*args)
29
29
  new(*args)
@@ -42,7 +42,7 @@ class MockRedis
42
42
  def id
43
43
  "redis://#{host}:#{port}/#{db}"
44
44
  end
45
- alias_method :location, :id
45
+ alias location id
46
46
 
47
47
  def call(command, &_block)
48
48
  send(*command)
@@ -63,7 +63,7 @@ class MockRedis
63
63
  def now
64
64
  options[:time_class].now
65
65
  end
66
- alias_method :time, :now
66
+ alias time now
67
67
 
68
68
  def time_at(timestamp)
69
69
  options[:time_class].at(timestamp)
@@ -8,6 +8,7 @@ require 'mock_redis/zset_methods'
8
8
  require 'mock_redis/sort_method'
9
9
  require 'mock_redis/indifferent_hash'
10
10
  require 'mock_redis/info_method'
11
+ require 'mock_redis/utility_methods'
11
12
 
12
13
  class MockRedis
13
14
  class Database
@@ -18,6 +19,7 @@ class MockRedis
18
19
  include ZsetMethods
19
20
  include SortMethod
20
21
  include InfoMethod
22
+ include UtilityMethods
21
23
 
22
24
  attr_reader :data, :expire_times
23
25
 
@@ -119,14 +121,17 @@ class MockRedis
119
121
  end
120
122
 
121
123
  def scan(cursor, opts = {})
122
- count = (opts[:count] || 10).to_i
123
- match = opts[:match] || '*'
124
-
125
- keys = data.keys
126
- limit = cursor + count
127
- next_cursor = limit >= keys.length ? '0' : limit.to_s
124
+ common_scan(data.keys, cursor, opts)
125
+ end
128
126
 
129
- [next_cursor, keys[cursor..limit].grep(redis_pattern_to_ruby_regex(match))]
127
+ def scan_each(opts = {}, &block)
128
+ return to_enum(:scan_each, opts) unless block_given?
129
+ cursor = 0
130
+ loop do
131
+ cursor, keys = scan(cursor, opts)
132
+ keys.each(&block)
133
+ break if cursor == '0'
134
+ end
130
135
  end
131
136
 
132
137
  def lastsave
@@ -224,6 +229,15 @@ class MockRedis
224
229
  end
225
230
  end
226
231
 
232
+ def script(subcommand, *args)
233
+ end
234
+
235
+ def evalsha(*args)
236
+ end
237
+
238
+ def eval(*args)
239
+ end
240
+
227
241
  private
228
242
 
229
243
  def assert_valid_timeout(timeout)
@@ -109,6 +109,21 @@ class MockRedis
109
109
  hmset(key, *kvpairs)
110
110
  end
111
111
 
112
+ def hscan(key, cursor, opts = {})
113
+ opts = opts.merge(key: lambda { |x| x[0] })
114
+ common_scan(hgetall(key).to_a, cursor, opts)
115
+ end
116
+
117
+ def hscan_each(key, opts = {}, &block)
118
+ return to_enum(:hscan_each, key, opts) unless block_given?
119
+ cursor = 0
120
+ loop do
121
+ cursor, values = hscan(key, cursor, opts)
122
+ values.each(&block)
123
+ break if cursor == '0'
124
+ end
125
+ end
126
+
112
127
  def hset(key, field, value)
113
128
  with_hash_at(key) { |h| h[field.to_s] = value.to_s }
114
129
  true
@@ -15,14 +15,14 @@ class MockRedis
15
15
  'tcp_port' => '6379',
16
16
  'uptime_in_days' => '0',
17
17
  'uptime_in_seconds' => '84215',
18
- }
18
+ }.freeze
19
19
 
20
20
  CLIENTS_INFO = {
21
21
  'blocked_clients' => '0',
22
22
  'client_biggest_input_buf' => '0',
23
23
  'client_longest_output_list' => '0',
24
24
  'connected_clients' => '1',
25
- }
25
+ }.freeze
26
26
 
27
27
  MEMORY_INFO = {
28
28
  'mem_allocator' => 'libc',
@@ -33,7 +33,7 @@ class MockRedis
33
33
  'used_memory_peak' => '1005424',
34
34
  'used_memory_peak_human' => '981.86K',
35
35
  'used_memory_rss' => '1904640',
36
- }
36
+ }.freeze
37
37
 
38
38
  PERSISTENCE_INFO = {
39
39
  'aof_current_rewrite_time_sec' => '-1',
@@ -49,7 +49,7 @@ class MockRedis
49
49
  'rdb_last_bgsave_status' => 'ok',
50
50
  'rdb_last_bgsave_time_sec' => '-1',
51
51
  'rdb_last_save_time' => '1361423635',
52
- }
52
+ }.freeze
53
53
 
54
54
  STATS_INFO = {
55
55
  'evicted_keys' => '0',
@@ -63,23 +63,23 @@ class MockRedis
63
63
  'rejected_connections' => '0',
64
64
  'total_commands_processed' => '196800',
65
65
  'total_connections_received' => '4359',
66
- }
66
+ }.freeze
67
67
 
68
68
  REPLICATION_INFO = {
69
69
  'role' => 'master',
70
70
  'connected_slaves' => '0',
71
- }
71
+ }.freeze
72
72
 
73
73
  CPU_INFO = {
74
74
  'used_cpu_sys' => '5.54',
75
75
  'used_cpu_sys_childrens' => '0.00',
76
76
  'used_cpu_user' => '7.65',
77
77
  'used_cpu_user_childrens' => '0.02',
78
- }
78
+ }.freeze
79
79
 
80
80
  KEYSPACE_INFO = {
81
81
  'db0' => 'keys=8,expires=0',
82
- }
82
+ }.freeze
83
83
 
84
84
  # The Ruby Redis client returns commandstats differently when it's called as
85
85
  # "INFO commandstats".
@@ -102,7 +102,7 @@ class MockRedis
102
102
  'slowlog' => { 'calls' => '136', 'usec' => '16815', 'usec_per_call' => '123.64' },
103
103
  'smembers' => { 'calls' => '58', 'usec' => '231', 'usec_per_call' => '3.98' },
104
104
  'sunionstore' => { 'calls' => '4185027', 'usec' => '11762454022', 'usec_per_call' => '2810.60' },
105
- }
105
+ }.freeze
106
106
 
107
107
  COMMAND_STATS_COMBINED_INFO = {
108
108
  'cmdstat_auth' => 'calls=572506,usec=2353182,usec_per_call=4.11',
@@ -122,7 +122,7 @@ class MockRedis
122
122
  'cmdstat_slowlog' => 'calls=136,usec=16815,usec_per_call=123.64',
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
126
  # rubocop:enable Metrics/LineLength
127
127
 
128
128
  DEFAULT_INFO = [
@@ -136,7 +136,7 @@ class MockRedis
136
136
  end
137
137
 
138
138
  index = index.to_i
139
- unless (0...llen(key)).include?(index)
139
+ unless (0...llen(key)).cover?(index)
140
140
  raise Redis::CommandError, 'ERR index out of range'
141
141
  end
142
142
 
@@ -44,7 +44,7 @@ class MockRedis
44
44
  else
45
45
  case current_db.type(key)
46
46
  when 'hash'
47
- dest.hmset(key, *(src.hgetall(key).map { |k, v| [k, v] }.flatten))
47
+ dest.hmset(key, *src.hgetall(key).map { |k, v| [k, v] }.flatten)
48
48
  when 'list'
49
49
  while value = src.rpop(key)
50
50
  dest.lpush(key, value)
@@ -95,7 +95,7 @@ class MockRedis
95
95
  if count > 0
96
96
  members.sample(count)
97
97
  else
98
- count.abs.times.map { members[rand(members.length)] }
98
+ Array.new(count.abs) { members[rand(members.length)] }
99
99
  end
100
100
  else
101
101
  members[rand(members.length)]
@@ -114,6 +114,20 @@ class MockRedis
114
114
  end
115
115
  end
116
116
 
117
+ def sscan(key, cursor, opts = {})
118
+ common_scan(smembers(key), cursor, opts)
119
+ end
120
+
121
+ def sscan_each(key, opts = {}, &block)
122
+ return to_enum(:sscan_each, key, opts) unless block_given?
123
+ cursor = 0
124
+ loop do
125
+ cursor, keys = sscan(key, cursor, opts)
126
+ keys.each(&block)
127
+ break if cursor == '0'
128
+ end
129
+ end
130
+
117
131
  def sunion(*keys)
118
132
  assert_has_args(keys, 'sunion')
119
133
  with_sets_at(*keys) { |*sets| sets.reduce(&:+).to_a }
@@ -140,7 +154,7 @@ class MockRedis
140
154
  else
141
155
  with_set_at(keys.first) do |set|
142
156
  with_sets_at(*(keys[1..-1])) do |*sets|
143
- blk.call(*([set] + sets))
157
+ yield(*([set] + sets))
144
158
  end
145
159
  end
146
160
  end
@@ -22,5 +22,21 @@ class MockRedis
22
22
  del(key)
23
23
  end
24
24
  end
25
+
26
+ def common_scan(values, cursor, opts = {})
27
+ count = (opts[:count] || 10).to_i
28
+ cursor = cursor.to_i
29
+ match = opts[:match] || '*'
30
+ key = opts[:key] || lambda { |x| x }
31
+
32
+ limit = cursor + count
33
+ next_cursor = limit >= values.length ? '0' : limit.to_s
34
+
35
+ filtered_values = values[cursor...limit].select do |val|
36
+ redis_pattern_to_ruby_regex(match).match(key.call(val))
37
+ end
38
+
39
+ [next_cursor, filtered_values]
40
+ end
25
41
  end
26
42
  end
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Defines the gem version.
2
4
  class MockRedis
3
- VERSION = '0.15.4'
5
+ VERSION = '0.16.0'.freeze
4
6
  end
@@ -23,11 +23,12 @@ class MockRedis
23
23
 
24
24
  def add(score, member)
25
25
  members.add(member)
26
- if score.to_f.to_i == score.to_f
27
- scores[member] = score.to_f.to_i
28
- else
29
- scores[member] = score.to_f
30
- end
26
+ scores[member] =
27
+ if score.to_f.to_i == score.to_f
28
+ score.to_f.to_i
29
+ else
30
+ score.to_f
31
+ end
31
32
  self
32
33
  end
33
34
 
@@ -128,6 +128,21 @@ class MockRedis
128
128
  with_zset_at(key) { |z| z.sorted_members.reverse.index(member.to_s) }
129
129
  end
130
130
 
131
+ def zscan(key, cursor, opts = {})
132
+ opts = opts.merge(key: lambda { |x| x[0] })
133
+ common_scan(zrange(key, 0, -1, withscores: true), cursor, opts)
134
+ end
135
+
136
+ def zscan_each(key, opts = {}, &block)
137
+ return to_enum(:zscan_each, key, opts) unless block_given?
138
+ cursor = 0
139
+ loop do
140
+ cursor, values = zscan(key, cursor, opts)
141
+ values.each(&block)
142
+ break if cursor == '0'
143
+ end
144
+ end
145
+
131
146
  def zscore(key, member)
132
147
  with_zset_at(key) do |z|
133
148
  score = z.score(member.to_s)
@@ -205,7 +220,7 @@ class MockRedis
205
220
  else
206
221
  with_zset_at(keys.first) do |set|
207
222
  with_zsets_at(*(keys[1..-1])) do |*sets|
208
- blk.call(*([set] + sets))
223
+ yield(*([set] + sets))
209
224
  end
210
225
  end
211
226
  end
@@ -230,7 +245,7 @@ class MockRedis
230
245
  def assert_scorey(value, message = 'ERR value is not a valid float')
231
246
  return if value =~ /\(?(\-|\+)inf/
232
247
 
233
- value = $1 if value.to_s.match(/\((.*)/)
248
+ value = $1 if value.to_s =~ /\((.*)/
234
249
  unless looks_like_float?(value)
235
250
  raise Redis::CommandError, message
236
251
  end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#eval(*)' do
4
+ it 'returns nothing' do
5
+ @redises.eval('return nil').should be_nil
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#evalsha(*)' do
4
+ let(:script) { 'return nil' }
5
+ let(:script_digest) { Digest::SHA1.hexdigest(script) }
6
+
7
+ it 'returns nothing' do
8
+ @redises.evalsha(script_digest).should be_nil
9
+ end
10
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#hscan_each' do
4
+ subject { MockRedis::Database.new(self) }
5
+
6
+ let(:key) { 'mock-redis-test:hscan_each' }
7
+
8
+ before do
9
+ allow(subject).to receive(:hgetall).and_return(collection)
10
+ end
11
+
12
+ context 'when no keys are found' do
13
+ let(:collection) { [] }
14
+
15
+ it 'does not iterate over any elements' do
16
+ results = subject.hscan_each(key).map do |k, v|
17
+ [k, v]
18
+ end
19
+ expect(results).to match_array(collection)
20
+ end
21
+ end
22
+
23
+ context 'when keys are found' do
24
+ context 'when no match filter is supplied' do
25
+ let(:collection) { Array.new(20) { |i| ["k#{i}", "v#{i}"] } }
26
+
27
+ it 'iterates over each item in the collection' do
28
+ results = subject.hscan_each(key).map do |k, v|
29
+ [k, v]
30
+ end
31
+ expect(results).to match_array(collection)
32
+ end
33
+ end
34
+
35
+ context 'when giving a custom match filter' do
36
+ let(:match) { 'k1*' }
37
+ let(:collection) { Array.new(12) { |i| ["k#{i}", "v#{i}"] } }
38
+ let(:expected) { [%w[k1 v1], %w[k10 v10], %w[k11 v11]] }
39
+
40
+ it 'iterates over each item in the filtered collection' do
41
+ results = subject.hscan_each(key, match: match).map do |k, v|
42
+ [k, v]
43
+ end
44
+ expect(results).to match_array(expected)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#hscan' do
4
+ let(:count) { 10 }
5
+ let(:match) { '*' }
6
+ let(:key) { 'mock-redis-test:hscan' }
7
+
8
+ context 'when the hash does not exist' do
9
+ it 'returns a 0 cursor and an empty collection' do
10
+ expect(@redises.hscan(key, 0, count: count, match: match)).to eq(['0', []])
11
+ end
12
+ end
13
+
14
+ context 'when the hash exists' do
15
+ before do
16
+ @redises.hset(key, 'k1', 'v1')
17
+ @redises.hset(key, 'k2', 'v2')
18
+ @redises.hset(key, 'k3', 'v3')
19
+ end
20
+
21
+ let(:expected) { ['0', [%w[k1 v1], %w[k2 v2], %w[k3 v3]]] }
22
+
23
+ it 'returns a 0 cursor and the collection' do
24
+ expect(@redises.hscan(key, 0, count: 10)).to eq(expected)
25
+ end
26
+ end
27
+ end
@@ -48,7 +48,7 @@ describe '#keys()' do
48
48
  ]
49
49
  end
50
50
 
51
- it "treats \? as a literal ?" do
51
+ it 'treats \\? as a literal ?' do
52
52
  @redises.keys('mock-redis-test:special-key\?').sort.should == [
53
53
  'mock-redis-test:special-key?',
54
54
  ]
@@ -68,7 +68,7 @@ describe '#keys()' do
68
68
  ]
69
69
  end
70
70
 
71
- it "treats \* as a literal *" do
71
+ it 'treats \\* as a literal *' do
72
72
  @redises.keys('mock-redis-test:special-key\*').sort.should == [
73
73
  'mock-redis-test:special-key*',
74
74
  ]
@@ -101,7 +101,7 @@ describe '#keys()' do
101
101
  end
102
102
 
103
103
  describe 'character classes ([a-c])' do
104
- it "specifies a range which matches any lowercase letter from \"a\" to \"c\"" do
104
+ it 'specifies a range which matches any lowercase letter from "a" to "c"' do
105
105
  @redises.keys('mock-redis-test:regexp-key4[a-c]').sort.should == [
106
106
  'mock-redis-test:regexp-key4a',
107
107
  'mock-redis-test:regexp-key4b',
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#scan_each' do
4
+ subject { MockRedis::Database.new(self) }
5
+
6
+ let(:match) { '*' }
7
+
8
+ before do
9
+ allow(subject).to receive_message_chain(:data, :keys).and_return(collection)
10
+ end
11
+
12
+ context 'when no keys are found' do
13
+ let(:collection) { [] }
14
+
15
+ it 'does not iterate over any elements' do
16
+ expect(subject.scan_each.to_a).to be_empty
17
+ end
18
+ end
19
+
20
+ context 'when keys are found' do
21
+ context 'when no match filter is supplied' do
22
+ let(:collection) { Array.new(20) { |i| "mock:key#{i}" } }
23
+
24
+ it 'iterates over each item in the collection' do
25
+ expect(subject.scan_each.to_a).to match_array(collection)
26
+ end
27
+ end
28
+
29
+ context 'when giving a custom match filter' do
30
+ let(:match) { 'mock:key*' }
31
+ let(:collection) { %w[mock:key mock:key2 mock:otherkey] }
32
+ let(:expected) { %w[mock:key mock:key2] }
33
+
34
+ it 'iterates over each item in the filtered collection' do
35
+ expect(subject.scan_each(match: match).to_a).to match_array(expected)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -7,7 +7,7 @@ describe '#scan' do
7
7
  let(:match) { '*' }
8
8
 
9
9
  before do
10
- expect(subject).to receive_message_chain(:data, :keys).and_return(collection)
10
+ allow(subject).to receive_message_chain(:data, :keys).and_return(collection)
11
11
  end
12
12
 
13
13
  context 'when no keys are found' do
@@ -20,16 +20,21 @@ describe '#scan' do
20
20
 
21
21
  context 'when keys are found' do
22
22
  context 'when count is lower than collection size' do
23
- let(:collection) { (count + 1).times.map { |i| "mock:key#{i}" } }
24
- let(:expected) { [count.to_s, collection] }
23
+ let(:collection) { Array.new(count * 2) { |i| "mock:key#{i}" } }
24
+ let(:expected_first) { [count.to_s, collection[0...count]] }
25
+ let(:expected_second) { ['0', collection[count..-1]] }
25
26
 
26
27
  it 'returns a the next cursor and the collection' do
27
- expect(subject.scan(0, count: count, match: match)).to eq(expected)
28
+ expect(subject.scan(0, count: count, match: match)).to eq(expected_first)
29
+ end
30
+
31
+ it 'returns the correct results of the next cursor' do
32
+ expect(subject.scan(count, count: count, match: match)).to eq(expected_second)
28
33
  end
29
34
  end
30
35
 
31
36
  context 'when count is greater or equal than collection size' do
32
- let(:collection) { count.times.map { |i| "mock:key#{i}" } }
37
+ let(:collection) { Array.new(count) { |i| "mock:key#{i}" } }
33
38
  let(:expected) { ['0', collection] }
34
39
 
35
40
  it 'returns a 0 cursor and the collection' do
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#script(subcommand, *args)' do
4
+ before { @key = 'mock-redis-test:script' }
5
+
6
+ it 'works with load subcommand' do
7
+ expect { @redises.send_without_checking(:script, :load, 'return 1') }.to_not raise_error
8
+ end
9
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#sscan_each' do
4
+ subject { MockRedis::Database.new(self) }
5
+
6
+ let(:key) { 'mock-redis-test:sscan_each' }
7
+
8
+ before do
9
+ allow(subject).to receive(:smembers).and_return(collection)
10
+ end
11
+
12
+ context 'when no keys are found' do
13
+ let(:collection) { [] }
14
+
15
+ it 'does not iterate over any elements' do
16
+ results = subject.sscan_each(key).map do |k|
17
+ k
18
+ end
19
+ expect(results).to match_array(collection)
20
+ end
21
+ end
22
+
23
+ context 'when keys are found' do
24
+ context 'when no match filter is supplied' do
25
+ let(:collection) { Array.new(20) { |i| "k#{i}" } }
26
+
27
+ it 'iterates over each item in the collection' do
28
+ results = subject.sscan_each(key).map do |k|
29
+ k
30
+ end
31
+ expect(results).to match_array(collection)
32
+ end
33
+ end
34
+
35
+ context 'when giving a custom match filter' do
36
+ let(:match) { 'k1*' }
37
+ let(:collection) { Array.new(12) { |i| "k#{i}" } }
38
+ let(:expected) { %w[k1 k10 k11] }
39
+
40
+ it 'iterates over each item in the filtered collection' do
41
+ results = subject.sscan_each(key, match: match).map do |k|
42
+ k
43
+ end
44
+ expect(results).to match_array(expected)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#sscan' do
4
+ let(:count) { 10 }
5
+ let(:match) { '*' }
6
+ let(:key) { 'mock-redis-test:sscan' }
7
+
8
+ before do
9
+ # The return order of the members is non-deterministic, so we sort them to compare
10
+ expect_any_instance_of(Redis).to receive(:sscan).and_wrap_original do |m, *args|
11
+ result = m.call(*args)
12
+ [result[0], result[1].sort]
13
+ end
14
+ expect_any_instance_of(MockRedis).to receive(:sscan).and_wrap_original do |m, *args|
15
+ result = m.call(*args)
16
+ [result[0], result[1].sort]
17
+ end
18
+ end
19
+
20
+ context 'when the set does not exist' do
21
+ it 'returns a 0 cursor and an empty collection' do
22
+ expect(@redises.sscan(key, 0, count: count, match: match)).to eq(['0', []])
23
+ end
24
+ end
25
+
26
+ context 'when the set exists' do
27
+ before do
28
+ @redises.sadd(key, 'Hello')
29
+ @redises.sadd(key, 'World')
30
+ @redises.sadd(key, 'Test')
31
+ end
32
+
33
+ let(:expected) { ['0', %w[Hello Test World]] }
34
+
35
+ it 'returns a 0 cursor and the collection' do
36
+ expect(@redises.sscan(key, 0, count: count)).to eq(expected)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#zscan_each' do
4
+ subject { MockRedis::Database.new(self) }
5
+
6
+ let(:key) { 'mock-redis-test:zscan_each' }
7
+
8
+ before do
9
+ allow(subject).to receive(:zrange).and_return(collection)
10
+ end
11
+
12
+ context 'when no keys are found' do
13
+ let(:collection) { [] }
14
+
15
+ it 'does not iterate over any elements' do
16
+ results = subject.zscan_each(key).map do |m, s|
17
+ [m, s]
18
+ end
19
+ expect(results).to match_array(collection)
20
+ end
21
+ end
22
+
23
+ context 'when keys are found' do
24
+ context 'when no match filter is supplied' do
25
+ let(:collection) { Array.new(20) { |i| ["m#{i}", i] } }
26
+
27
+ it 'iterates over each item in the collection' do
28
+ results = subject.zscan_each(key).map do |m, s|
29
+ [m, s]
30
+ end
31
+ expect(results).to match_array(collection)
32
+ end
33
+ end
34
+
35
+ context 'when giving a custom match filter' do
36
+ let(:match) { 'm1*' }
37
+ let(:collection) { Array.new(12) { |i| ["m#{i}", i] } }
38
+ let(:expected) { [['m1', 1], ['m10', 10], ['m11', 11]] }
39
+
40
+ it 'iterates over each item in the filtered collection' do
41
+ results = subject.zscan_each(key, match: match).map do |m, s|
42
+ [m, s]
43
+ end
44
+ expect(results).to match_array(expected)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe '#zscan' do
4
+ let(:count) { 10 }
5
+ let(:match) { '*' }
6
+ let(:key) { 'mock-redis-test:zscan' }
7
+
8
+ context 'when the zset does not exist' do
9
+ it 'returns a 0 cursor and an empty collection' do
10
+ expect(@redises.zscan(key, 0, count: count, match: match)).to eq(['0', []])
11
+ end
12
+ end
13
+
14
+ context 'when the zset exists' do
15
+ before do
16
+ @redises.zadd(key, 1.0, 'member1')
17
+ @redises.zadd(key, 2.0, 'member2')
18
+ end
19
+
20
+ it 'returns a 0 cursor and the collection' do
21
+ result = @redises.zscan(key, 0)
22
+ expect(result[0]).to eq('0')
23
+ expect(result[1]).to match_array([['member1', 1.0], ['member2', 2.0]])
24
+ end
25
+ end
26
+ end
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.15.4
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brigade Engineering
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-11-13 00:00:00.000000000 Z
12
+ date: 2016-01-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -126,6 +126,8 @@ files:
126
126
  - spec/commands/del_spec.rb
127
127
  - spec/commands/disconnect_spec.rb
128
128
  - spec/commands/echo_spec.rb
129
+ - spec/commands/eval_spec.rb
130
+ - spec/commands/evalsha_spec.rb
129
131
  - spec/commands/exists_spec.rb
130
132
  - spec/commands/expire_spec.rb
131
133
  - spec/commands/expireat_spec.rb
@@ -147,6 +149,8 @@ files:
147
149
  - spec/commands/hlen_spec.rb
148
150
  - spec/commands/hmget_spec.rb
149
151
  - spec/commands/hmset_spec.rb
152
+ - spec/commands/hscan_each_spec.rb
153
+ - spec/commands/hscan_spec.rb
150
154
  - spec/commands/hset_spec.rb
151
155
  - spec/commands/hsetnx_spec.rb
152
156
  - spec/commands/hvals_spec.rb
@@ -191,8 +195,10 @@ files:
191
195
  - spec/commands/rpushx_spec.rb
192
196
  - spec/commands/sadd_spec.rb
193
197
  - spec/commands/save_spec.rb
198
+ - spec/commands/scan_each_spec.rb
194
199
  - spec/commands/scan_spec.rb
195
200
  - spec/commands/scard_spec.rb
201
+ - spec/commands/script_spec.rb
196
202
  - spec/commands/sdiff_spec.rb
197
203
  - spec/commands/sdiffstore_spec.rb
198
204
  - spec/commands/select_spec.rb
@@ -212,6 +218,8 @@ files:
212
218
  - spec/commands/spop_spec.rb
213
219
  - spec/commands/srandmember_spec.rb
214
220
  - spec/commands/srem_spec.rb
221
+ - spec/commands/sscan_each_spec.rb
222
+ - spec/commands/sscan_spec.rb
215
223
  - spec/commands/strlen_spec.rb
216
224
  - spec/commands/sunion_spec.rb
217
225
  - spec/commands/sunionstore_spec.rb
@@ -233,6 +241,8 @@ files:
233
241
  - spec/commands/zrevrange_spec.rb
234
242
  - spec/commands/zrevrangebyscore_spec.rb
235
243
  - spec/commands/zrevrank_spec.rb
244
+ - spec/commands/zscan_each_spec.rb
245
+ - spec/commands/zscan_spec.rb
236
246
  - spec/commands/zscore_spec.rb
237
247
  - spec/commands/zunionstore_spec.rb
238
248
  - spec/mock_redis_spec.rb
@@ -287,6 +297,8 @@ test_files:
287
297
  - spec/commands/del_spec.rb
288
298
  - spec/commands/disconnect_spec.rb
289
299
  - spec/commands/echo_spec.rb
300
+ - spec/commands/eval_spec.rb
301
+ - spec/commands/evalsha_spec.rb
290
302
  - spec/commands/exists_spec.rb
291
303
  - spec/commands/expire_spec.rb
292
304
  - spec/commands/expireat_spec.rb
@@ -308,6 +320,8 @@ test_files:
308
320
  - spec/commands/hlen_spec.rb
309
321
  - spec/commands/hmget_spec.rb
310
322
  - spec/commands/hmset_spec.rb
323
+ - spec/commands/hscan_each_spec.rb
324
+ - spec/commands/hscan_spec.rb
311
325
  - spec/commands/hset_spec.rb
312
326
  - spec/commands/hsetnx_spec.rb
313
327
  - spec/commands/hvals_spec.rb
@@ -352,8 +366,10 @@ test_files:
352
366
  - spec/commands/rpushx_spec.rb
353
367
  - spec/commands/sadd_spec.rb
354
368
  - spec/commands/save_spec.rb
369
+ - spec/commands/scan_each_spec.rb
355
370
  - spec/commands/scan_spec.rb
356
371
  - spec/commands/scard_spec.rb
372
+ - spec/commands/script_spec.rb
357
373
  - spec/commands/sdiff_spec.rb
358
374
  - spec/commands/sdiffstore_spec.rb
359
375
  - spec/commands/select_spec.rb
@@ -373,6 +389,8 @@ test_files:
373
389
  - spec/commands/spop_spec.rb
374
390
  - spec/commands/srandmember_spec.rb
375
391
  - spec/commands/srem_spec.rb
392
+ - spec/commands/sscan_each_spec.rb
393
+ - spec/commands/sscan_spec.rb
376
394
  - spec/commands/strlen_spec.rb
377
395
  - spec/commands/sunion_spec.rb
378
396
  - spec/commands/sunionstore_spec.rb
@@ -394,6 +412,8 @@ test_files:
394
412
  - spec/commands/zrevrange_spec.rb
395
413
  - spec/commands/zrevrangebyscore_spec.rb
396
414
  - spec/commands/zrevrank_spec.rb
415
+ - spec/commands/zscan_each_spec.rb
416
+ - spec/commands/zscan_spec.rb
397
417
  - spec/commands/zscore_spec.rb
398
418
  - spec/commands/zunionstore_spec.rb
399
419
  - spec/mock_redis_spec.rb