mock_redis 0.15.4 → 0.16.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 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