mock_redis 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/Gemfile +1 -1
  3. data/lib/mock_redis/assertions.rb +2 -2
  4. data/lib/mock_redis/database.rb +16 -8
  5. data/lib/mock_redis/expire_wrapper.rb +2 -2
  6. data/lib/mock_redis/hash_methods.rb +12 -6
  7. data/lib/mock_redis/list_methods.rb +10 -8
  8. data/lib/mock_redis/multi_db_wrapper.rb +3 -3
  9. data/lib/mock_redis/pipelined_wrapper.rb +45 -0
  10. data/lib/mock_redis/set_methods.rb +14 -5
  11. data/lib/mock_redis/string_methods.rb +6 -6
  12. data/lib/mock_redis/transaction_wrapper.rb +13 -8
  13. data/lib/mock_redis/version.rb +1 -1
  14. data/lib/mock_redis/zset_methods.rb +52 -22
  15. data/lib/mock_redis.rb +92 -5
  16. data/mock_redis.gemspec +1 -1
  17. data/spec/cloning_spec.rb +1 -1
  18. data/spec/commands/blpop_spec.rb +3 -3
  19. data/spec/commands/brpop_spec.rb +3 -3
  20. data/spec/commands/brpoplpush_spec.rb +3 -3
  21. data/spec/commands/hdel_spec.rb +5 -0
  22. data/spec/commands/lpush_spec.rb +7 -0
  23. data/spec/commands/mapped_hmset_spec.rb +7 -1
  24. data/spec/commands/move_spec.rb +2 -2
  25. data/spec/commands/msetnx_spec.rb +2 -2
  26. data/spec/commands/pipelined_spec.rb +12 -0
  27. data/spec/commands/rename_spec.rb +7 -0
  28. data/spec/commands/renamenx_spec.rb +7 -0
  29. data/spec/commands/rpush_spec.rb +7 -0
  30. data/spec/commands/sadd_spec.rb +1 -1
  31. data/spec/commands/sdiff_spec.rb +1 -1
  32. data/spec/commands/sdiffstore_spec.rb +3 -3
  33. data/spec/commands/sinterstore_spec.rb +2 -2
  34. data/spec/commands/smembers_spec.rb +4 -4
  35. data/spec/commands/srem_spec.rb +5 -0
  36. data/spec/commands/sunion_spec.rb +2 -2
  37. data/spec/commands/sunionstore_spec.rb +3 -3
  38. data/spec/commands/watch_spec.rb +2 -2
  39. data/spec/commands/zadd_spec.rb +6 -1
  40. data/spec/commands/zcount_spec.rb +8 -0
  41. data/spec/commands/zincrby_spec.rb +4 -4
  42. data/spec/commands/zinterstore_spec.rb +7 -7
  43. data/spec/commands/zrange_spec.rb +6 -2
  44. data/spec/commands/zrangebyscore_spec.rb +2 -2
  45. data/spec/commands/zrem_spec.rb +5 -0
  46. data/spec/commands/zrevrange_spec.rb +2 -2
  47. data/spec/commands/zrevrangebyscore_spec.rb +2 -2
  48. data/spec/commands/zscore_spec.rb +2 -2
  49. data/spec/commands/zunionstore_spec.rb +9 -9
  50. data/spec/mock_redis_spec.rb +21 -0
  51. data/spec/support/redis_multiplexer.rb +23 -19
  52. data/spec/transactions_spec.rb +17 -0
  53. metadata +67 -84
  54. data/lib/mock_redis/distributed.rb +0 -6
@@ -19,12 +19,12 @@ describe "#zrevrange(key, start, stop [, :with_scores => true])" do
19
19
 
20
20
  it "returns the scores when :with_scores is specified" do
21
21
  @redises.zrevrange(@key, 2, 3, :with_scores => true).
22
- should == ["Adams", "2", "Washington", "1"]
22
+ should == [["Adams", 2.0], ["Washington", 1.0]]
23
23
  end
24
24
 
25
25
  it "returns the scores when :withscores is specified" do
26
26
  @redises.zrevrange(@key, 2, 3, :withscores => true).
27
- should == ["Adams", "2", "Washington", "1"]
27
+ should == [["Adams", 2.0], ["Washington", 1.0]]
28
28
  end
29
29
 
30
30
  it_should_behave_like "a zset-only command"
@@ -15,12 +15,12 @@ describe "#zrevrangebyscore(key, start, stop [:with_scores => true] [:limit => [
15
15
 
16
16
  it "returns the scores when :with_scores is specified" do
17
17
  @redises.zrevrangebyscore(@key, 4, 3, :with_scores => true).
18
- should == %w[Madison 4 Jefferson 3]
18
+ should == [["Madison", 4.0], ["Jefferson", 3.0]]
19
19
  end
20
20
 
21
21
  it "returns the scores when :withscores is specified" do
22
22
  @redises.zrevrangebyscore(@key, 4, 3, :withscores => true).
23
- should == %w[Madison 4 Jefferson 3]
23
+ should == [["Madison", 4.0], ["Jefferson", 3.0]]
24
24
  end
25
25
 
26
26
  it "treats +inf as positive infinity" do
@@ -5,13 +5,13 @@ describe "#zscore(key, member)" do
5
5
 
6
6
  it "returns the score as a string" do
7
7
  @redises.zadd(@key, 0.25, 'foo').should be_true
8
- @redises.zscore(@key, 'foo').should == "0.25"
8
+ @redises.zscore(@key, 'foo').should == 0.25
9
9
  end
10
10
 
11
11
  it "handles integer members correctly" do
12
12
  member = 11
13
13
  @redises.zadd(@key, 0.25, member).should be_true
14
- @redises.zscore(@key, member).should == "0.25"
14
+ @redises.zscore(@key, member).should == 0.25
15
15
  end
16
16
 
17
17
  it "returns nil if member is not present in the set" do
@@ -24,7 +24,7 @@ describe "#zunionstore(destination, keys, [:weights => [w,w,], [:aggregate => :s
24
24
  it "sums the members' scores by default" do
25
25
  @redises.zunionstore(@dest, [@set1, @set2, @set3])
26
26
  @redises.zrange(@dest, 0, -1, :with_scores => true).should ==
27
- %w[one 3 three 3 two 4]
27
+ [["one", 3.0], ["three", 3.0], ["two", 4.0]]
28
28
  end
29
29
 
30
30
  it "removes existing elements in destination" do
@@ -32,7 +32,7 @@ describe "#zunionstore(destination, keys, [:weights => [w,w,], [:aggregate => :s
32
32
 
33
33
  @redises.zunionstore(@dest, [@set1])
34
34
  @redises.zrange(@dest, 0, -1, :with_scores => true).should ==
35
- %w[one 1]
35
+ [["one", 1.0]]
36
36
  end
37
37
 
38
38
  it "raises an error if keys is empty" do
@@ -45,7 +45,7 @@ describe "#zunionstore(destination, keys, [:weights => [w,w,], [:aggregate => :s
45
45
  it "multiplies the scores by the weights while aggregating" do
46
46
  @redises.zunionstore(@dest, [@set1, @set2, @set3], :weights => [2, 3, 5])
47
47
  @redises.zrange(@dest, 0, -1, :with_scores => true).should ==
48
- %w[one 10 three 15 two 16]
48
+ [["one", 10.0], ["three", 15.0], ["two", 16.0]]
49
49
  end
50
50
 
51
51
  it "raises an error if the number of weights != the number of keys" do
@@ -69,30 +69,30 @@ describe "#zunionstore(destination, keys, [:weights => [w,w,], [:aggregate => :s
69
69
  it "aggregates scores with min when :aggregate => :min is specified" do
70
70
  @redises.zunionstore(@dest, [@bigs, @smalls], :aggregate => :min)
71
71
  @redises.zrange(@dest, 0, -1, :with_scores => true).should ==
72
- %w[bert 1 ernie 2]
72
+ [["bert", 1.0], ["ernie", 2.0]]
73
73
  end
74
74
 
75
75
  it "aggregates scores with max when :aggregate => :max is specified" do
76
76
  @redises.zunionstore(@dest, [@bigs, @smalls], :aggregate => :max)
77
77
  @redises.zrange(@dest, 0, -1, :with_scores => true).should ==
78
- %w[bert 100 ernie 200]
78
+ [["bert", 100.0], ["ernie", 200.0]]
79
79
  end
80
80
 
81
81
  it "ignores scores for missing members" do
82
82
  @redises.zadd(@smalls, 3, 'grover')
83
83
  @redises.zunionstore(@dest, [@bigs, @smalls], :aggregate => :min)
84
- @redises.zscore(@dest, 'grover').should == '3'
84
+ @redises.zscore(@dest, 'grover').should == 3.0
85
85
 
86
86
  @redises.zunionstore(@dest, [@bigs, @smalls], :aggregate => :max)
87
- @redises.zscore(@dest, 'grover').should == '3'
87
+ @redises.zscore(@dest, 'grover').should == 3.0
88
88
  end
89
89
 
90
90
  it "allows 'min', 'MIN', etc. as aliases for :min" do
91
91
  @redises.zunionstore(@dest, [@bigs, @smalls], :aggregate => 'min')
92
- @redises.zscore(@dest, 'bert').should == '1'
92
+ @redises.zscore(@dest, 'bert').should == 1.0
93
93
 
94
94
  @redises.zunionstore(@dest, [@bigs, @smalls], :aggregate => 'MIN')
95
- @redises.zscore(@dest, 'bert').should == '1'
95
+ @redises.zscore(@dest, 'bert').should == 1.0
96
96
  end
97
97
 
98
98
  it "raises an error for unknown aggregation function" do
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe MockRedis do
4
+
5
+ context "with passed options" do
6
+ before do
7
+ @mock = MockRedis.new(:url => "redis://127.0.0.1:6379/1")
8
+ end
9
+
10
+ it "should correctly parse options" do
11
+ @mock.host.should == "127.0.0.1"
12
+ @mock.port.should == 6379
13
+ @mock.db.should == 1
14
+ end
15
+
16
+ it "should have an id equal to redis url" do
17
+ @mock.id.should == "redis://127.0.0.1:6379/1"
18
+ end
19
+ end
20
+
21
+ end
@@ -11,13 +11,30 @@ class RedisMultiplexer < BlankSlate
11
11
  end
12
12
 
13
13
  def method_missing(method, *args, &blk)
14
- mock_retval, mock_error = catch_errors { @mock_redis.send(method, *args, &blk) }
15
- real_retval, real_error = catch_errors { @real_redis.send(method, *args, &blk) }
14
+ # if we're in a Redis command that accepts a block, and we execute more redis commands, ONLY execute them
15
+ # on the Redis implementation that the block came from.
16
+ # e.g. if a pipelined command is started on a MockRedis object, DON'T send commands inside the pipelined block
17
+ # to the real Redis object, as that one WON'T be inside a pipelined command, and we'll see weird behaviour
18
+ if blk
19
+ @in_mock_block = true
20
+ @in_redis_block = false
21
+ end
22
+ mock_retval, mock_error = catch_errors { @in_redis_block ? :no_op : @mock_redis.send(method, *args, &blk) }
23
+
24
+ if blk
25
+ @in_mock_block = false
26
+ @in_redis_block = true
27
+ end
28
+ real_retval, real_error = catch_errors { @in_mock_block ? :no_op : @real_redis.send(method, *args, &blk) }
16
29
 
17
- mock_retval = handle_special_cases(method, mock_retval)
18
- real_retval = handle_special_cases(method, real_retval)
30
+ if blk
31
+ @in_mock_block = false
32
+ @in_redis_block = false
33
+ end
19
34
 
20
- if (!equalish?(mock_retval, real_retval) && !mock_error && !real_error)
35
+ if (mock_retval == :no_op || real_retval == :no_op)
36
+ # ignore, we were inside a block (like pipelined)
37
+ elsif (!equalish?(mock_retval, real_retval) && !mock_error && !real_error)
21
38
  # no exceptions, just different behavior
22
39
  raise MismatchedResponse,
23
40
  "Mock failure: responses not equal.\n" +
@@ -49,7 +66,7 @@ class RedisMultiplexer < BlankSlate
49
66
  if a == b
50
67
  true
51
68
  elsif a.is_a?(Array) && b.is_a?(Array)
52
- a.zip(b).all? {|(x,y)| equalish?(x,y)}
69
+ a.collect(&:to_s).sort == b.collect(&:to_s).sort
53
70
  elsif a.is_a?(Exception) && b.is_a?(Exception)
54
71
  a.class == b.class && a.message == b.message
55
72
  else
@@ -60,19 +77,6 @@ class RedisMultiplexer < BlankSlate
60
77
  def mock() @mock_redis end
61
78
  def real() @real_redis end
62
79
 
63
- # Some commands require special handling due to nondeterminism in
64
- # the returned values.
65
- def handle_special_cases(method, value)
66
- case method.to_s
67
- when 'keys', 'hkeys', 'sdiff', 'sinter', 'smembers', 'sunion'
68
- # The order is irrelevant, but [a,b] != [b,a] in Ruby, so we
69
- # sort the returned values so we can ignore the order.
70
- value.sort if value
71
- else
72
- value
73
- end
74
- end
75
-
76
80
  # Used in cleanup before() blocks.
77
81
  def send_without_checking(method, *args)
78
82
  @mock_redis.send(method, *args)
@@ -16,6 +16,23 @@ describe 'transactions (multi/exec/discard)' do
16
16
  @redises.multi
17
17
  end.should raise_error(RuntimeError)
18
18
  end
19
+
20
+ it "cleanup the state of tansaction wrapper if an exception occurs while a transaction is being processed" do
21
+ lambda do
22
+ @redises.mock.multi do |r|
23
+ raise "i'm a command that fails"
24
+ end
25
+ end.should raise_error(RuntimeError)
26
+
27
+ # before the fix this used to raised a #<RuntimeError: ERR MULTI calls can not be nested>
28
+ lambda do
29
+ @redises.mock.multi do |r|
30
+ # do stuff that succeed
31
+ s.set(nil, 'string')
32
+ end
33
+ end.should_not raise_error(RuntimeError)
34
+
35
+ end
19
36
  end
20
37
 
21
38
  context "#blocks" do
metadata CHANGED
@@ -1,86 +1,73 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: mock_redis
3
- version: !ruby/object:Gem::Version
4
- hash: 13
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 4
9
- - 1
10
- segments_generated: true
11
- version: 0.4.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ prerelease:
12
6
  platform: ruby
13
- authors:
7
+ authors:
14
8
  - Causes Engineering
15
9
  - Samuel Merritt
16
10
  autorequire:
17
11
  bindir: bin
18
12
  cert_chain: []
19
-
20
- date: 2012-03-24 00:00:00 -07:00
21
- default_executable:
22
- dependencies:
23
- - !ruby/object:Gem::Dependency
24
- version_requirements: &id001 !ruby/object:Gem::Requirement
13
+ date: 2012-08-27 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ requirement: !ruby/object:Gem::Requirement
25
18
  none: false
26
- requirements:
19
+ requirements:
27
20
  - - ~>
28
- - !ruby/object:Gem::Version
29
- hash: 63
30
- segments:
31
- - 0
32
- - 9
33
- - 2
34
- segments_generated: true
21
+ - !ruby/object:Gem::Version
35
22
  version: 0.9.2
36
- requirement: *id001
37
- name: rake
38
- prerelease: false
39
23
  type: :development
40
- - !ruby/object:Gem::Dependency
41
- version_requirements: &id002 !ruby/object:Gem::Requirement
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
42
26
  none: false
43
- requirements:
27
+ requirements:
44
28
  - - ~>
45
- - !ruby/object:Gem::Version
46
- hash: 5
47
- segments:
48
- - 2
49
- - 2
50
- - 1
51
- segments_generated: true
52
- version: 2.2.1
53
- requirement: *id002
29
+ - !ruby/object:Gem::Version
30
+ version: 0.9.2
31
+ - !ruby/object:Gem::Dependency
54
32
  name: redis
55
- prerelease: false
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: 3.0.0
56
39
  type: :development
57
- - !ruby/object:Gem::Dependency
58
- version_requirements: &id003 !ruby/object:Gem::Requirement
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
59
42
  none: false
60
- requirements:
43
+ requirements:
61
44
  - - ~>
62
- - !ruby/object:Gem::Version
63
- hash: 23
64
- segments:
65
- - 2
66
- - 6
67
- - 0
68
- segments_generated: true
69
- version: 2.6.0
70
- requirement: *id003
45
+ - !ruby/object:Gem::Version
46
+ version: 3.0.0
47
+ - !ruby/object:Gem::Dependency
71
48
  name: rspec
72
- prerelease: false
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 2.6.0
73
55
  type: :development
74
- description: Instantiate one with `redis = MockRedis.new` and treat it like you would a normal Redis object. It supports all the usual Redis operations.
75
- email:
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: 2.6.0
63
+ description: Instantiate one with `redis = MockRedis.new` and treat it like you would
64
+ a normal Redis object. It supports all the usual Redis operations.
65
+ email:
76
66
  - eng@causes.com
77
67
  executables: []
78
-
79
68
  extensions: []
80
-
81
69
  extra_rdoc_files: []
82
-
83
- files:
70
+ files:
84
71
  - .gitignore
85
72
  - .mailmap
86
73
  - .rspec
@@ -92,12 +79,12 @@ files:
92
79
  - lib/mock_redis.rb
93
80
  - lib/mock_redis/assertions.rb
94
81
  - lib/mock_redis/database.rb
95
- - lib/mock_redis/distributed.rb
96
82
  - lib/mock_redis/exceptions.rb
97
83
  - lib/mock_redis/expire_wrapper.rb
98
84
  - lib/mock_redis/hash_methods.rb
99
85
  - lib/mock_redis/list_methods.rb
100
86
  - lib/mock_redis/multi_db_wrapper.rb
87
+ - lib/mock_redis/pipelined_wrapper.rb
101
88
  - lib/mock_redis/set_methods.rb
102
89
  - lib/mock_redis/string_methods.rb
103
90
  - lib/mock_redis/transaction_wrapper.rb
@@ -216,6 +203,7 @@ files:
216
203
  - spec/commands/zrevrank_spec.rb
217
204
  - spec/commands/zscore_spec.rb
218
205
  - spec/commands/zunionstore_spec.rb
206
+ - spec/mock_redis_spec.rb
219
207
  - spec/spec_helper.rb
220
208
  - spec/support/redis_multiplexer.rb
221
209
  - spec/support/shared_examples/only_operates_on_hashes.rb
@@ -224,43 +212,37 @@ files:
224
212
  - spec/support/shared_examples/only_operates_on_strings.rb
225
213
  - spec/support/shared_examples/only_operates_on_zsets.rb
226
214
  - spec/transactions_spec.rb
227
- has_rdoc: true
228
215
  homepage: https://github.com/causes/mock_redis
229
216
  licenses: []
230
-
231
217
  post_install_message:
232
218
  rdoc_options: []
233
-
234
- require_paths:
219
+ require_paths:
235
220
  - lib
236
- required_ruby_version: !ruby/object:Gem::Requirement
221
+ required_ruby_version: !ruby/object:Gem::Requirement
237
222
  none: false
238
- requirements:
239
- - - ">="
240
- - !ruby/object:Gem::Version
241
- hash: 3
242
- segments:
223
+ requirements:
224
+ - - ! '>='
225
+ - !ruby/object:Gem::Version
226
+ version: '0'
227
+ segments:
243
228
  - 0
244
- segments_generated: true
245
- version: "0"
246
- required_rubygems_version: !ruby/object:Gem::Requirement
229
+ hash: 2382509530287634625
230
+ required_rubygems_version: !ruby/object:Gem::Requirement
247
231
  none: false
248
- requirements:
249
- - - ">="
250
- - !ruby/object:Gem::Version
251
- hash: 3
252
- segments:
232
+ requirements:
233
+ - - ! '>='
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
236
+ segments:
253
237
  - 0
254
- segments_generated: true
255
- version: "0"
238
+ hash: 2382509530287634625
256
239
  requirements: []
257
-
258
240
  rubyforge_project:
259
- rubygems_version: 1.3.7
241
+ rubygems_version: 1.8.23
260
242
  signing_key:
261
243
  specification_version: 3
262
244
  summary: Redis mock that just lives in memory; useful for testing.
263
- test_files:
245
+ test_files:
264
246
  - spec/cloning_spec.rb
265
247
  - spec/commands/append_spec.rb
266
248
  - spec/commands/auth_spec.rb
@@ -370,6 +352,7 @@ test_files:
370
352
  - spec/commands/zrevrank_spec.rb
371
353
  - spec/commands/zscore_spec.rb
372
354
  - spec/commands/zunionstore_spec.rb
355
+ - spec/mock_redis_spec.rb
373
356
  - spec/spec_helper.rb
374
357
  - spec/support/redis_multiplexer.rb
375
358
  - spec/support/shared_examples/only_operates_on_hashes.rb
@@ -1,6 +0,0 @@
1
- class MockRedis
2
- def pipelined(options = {})
3
- yield
4
- nil
5
- end
6
- end