redis-store-pika 1.9.2.1

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.
@@ -0,0 +1,316 @@
1
+ require 'test_helper'
2
+
3
+ describe "Redis::Store::Namespace" do
4
+ def setup
5
+ @namespace = "theplaylist"
6
+ @store = Redis::Store.new :namespace => @namespace, :serializer => nil
7
+ @client = @store.instance_variable_get(:@client)
8
+ @rabbit = "bunny"
9
+ @default_store = Redis::Store.new
10
+ @other_namespace = 'other'
11
+ @other_store = Redis::Store.new :namespace => @other_namespace
12
+ end
13
+
14
+ def teardown
15
+ @store.flushdb
16
+ @store.quit
17
+
18
+ @default_store.flushdb
19
+ @default_store.quit
20
+
21
+ @other_store.flushdb
22
+ @other_store.quit
23
+ end
24
+
25
+ it "only decorates instances that need to be namespaced" do
26
+ store = Redis::Store.new
27
+ client = store.instance_variable_get(:@client)
28
+ # `call_v` used since redis-rb 5.0
29
+ client_call_method_name = client.respond_to?(:call_v) ? :call_v : :call
30
+ client.expects(client_call_method_name).with([:get, "rabbit"])
31
+ store.get("rabbit")
32
+ end
33
+
34
+ it "doesn't namespace a key which is already namespaced" do
35
+ _(@store.send(:interpolate, "#{@namespace}:rabbit")).must_equal("#{@namespace}:rabbit")
36
+ end
37
+
38
+ it "should only delete namespaced keys" do
39
+ @default_store.set 'abc', 'cba'
40
+ @store.set 'def', 'fed'
41
+
42
+ @store.flushdb
43
+ _(@store.get('def')).must_be_nil
44
+ _(@default_store.get('abc')).must_equal('cba')
45
+ end
46
+
47
+ it 'should allow to change namespace on the fly' do
48
+ @default_store.set 'abc', 'cba'
49
+ @other_store.set 'foo', 'bar'
50
+
51
+ _(@default_store.keys.sort).must_equal ['abc', 'other:foo']
52
+
53
+ @default_store.with_namespace(@other_namespace) do
54
+ _(@default_store.keys).must_equal ['foo']
55
+ _(@default_store.get('foo')).must_equal('bar')
56
+ end
57
+ end
58
+
59
+ it "should not try to delete missing namespaced keys" do
60
+ empty_store = Redis::Store.new :namespace => 'empty'
61
+ empty_store.flushdb
62
+ _(empty_store.keys).must_be_empty
63
+ end
64
+
65
+ it "should work with dynamic namespace" do
66
+ $ns = "ns1"
67
+ dyn_store = Redis::Store.new :namespace => -> { $ns }
68
+ dyn_store.set 'key', 'x'
69
+ $ns = "ns2"
70
+ dyn_store.set 'key', 'y'
71
+ $ns = "ns3"
72
+ dyn_store.set 'key', 'z'
73
+ dyn_store.flushdb
74
+ r3 = dyn_store.get 'key'
75
+ $ns = "ns2"
76
+ r2 = dyn_store.get 'key'
77
+ $ns = "ns1"
78
+ r1 = dyn_store.get 'key'
79
+ _(r1).must_equal('x') && _(r2).must_equal('y') && _(r3).must_be_nil
80
+ end
81
+
82
+ it "namespaces setex and ttl" do
83
+ @store.flushdb
84
+ @other_store.flushdb
85
+
86
+ @store.setex('foo', 30, 'bar')
87
+ _(@store.ttl('foo')).must_be_close_to(30)
88
+ _(@store.get('foo')).must_equal('bar')
89
+
90
+ _(@other_store.ttl('foo')).must_equal(-2)
91
+ _(@other_store.get('foo')).must_be_nil
92
+ end
93
+
94
+ describe 'method calls' do
95
+ let(:store) { Redis::Store.new :namespace => @namespace, :serializer => nil }
96
+ let(:client) { store.instance_variable_get(:@client) }
97
+ let(:client_call_method_name) do
98
+ # `call_v` used since redis-rb 5.0
99
+ client.respond_to?(:call_v) ? :call_v : :call
100
+ end
101
+
102
+ it "should namespace get" do
103
+ client.expects(client_call_method_name).with([:get, "#{@namespace}:rabbit"]).once
104
+ store.get("rabbit")
105
+ end
106
+
107
+ it "should namespace set" do
108
+ client.expects(client_call_method_name).with([:set, "#{@namespace}:rabbit", @rabbit])
109
+ store.set "rabbit", @rabbit
110
+ end
111
+
112
+ it "should namespace setnx" do
113
+ client.expects(client_call_method_name).with([:setnx, "#{@namespace}:rabbit", @rabbit])
114
+ store.setnx "rabbit", @rabbit
115
+ end
116
+
117
+ it "should namespace del with single key" do
118
+ client.expects(client_call_method_name).with([:del, "#{@namespace}:rabbit"])
119
+ store.del "rabbit"
120
+ end
121
+
122
+ it "should namespace del with multiple keys" do
123
+ client.expects(client_call_method_name).with([:del, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit"])
124
+ store.del "rabbit", "white_rabbit"
125
+ end
126
+
127
+ it "should namespace keys" do
128
+ store.set "rabbit", @rabbit
129
+ _(store.keys("rabb*")).must_equal [ "rabbit" ]
130
+ end
131
+
132
+ it "should namespace scan when a pattern is given" do
133
+ store.set "rabbit", @rabbit
134
+ cursor = "0"
135
+ keys = []
136
+ begin
137
+ cursor, matched_keys = store.scan(cursor, match: "rabb*")
138
+ keys = keys.concat(matched_keys) unless matched_keys.empty?
139
+ end until cursor == "0"
140
+ _(keys).must_equal [ "rabbit" ]
141
+ end
142
+
143
+ it "should namespace exists" do
144
+ client.expects(client_call_method_name).with([:exists, "#{@namespace}:rabbit"])
145
+ store.exists "rabbit"
146
+ end
147
+
148
+ it "should namespace incrby" do
149
+ client.expects(client_call_method_name).with([:incrby, "#{@namespace}:counter", 1])
150
+ store.incrby "counter", 1
151
+ end
152
+
153
+ it "should namespace decrby" do
154
+ client.expects(client_call_method_name).with([:decrby, "#{@namespace}:counter", 1])
155
+ store.decrby "counter", 1
156
+ end
157
+
158
+ it "should namespace mget" do
159
+ client.expects(client_call_method_name).with([:mget, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit"]).returns(%w[ foo bar ])
160
+ store.mget "rabbit", "white_rabbit" do |result|
161
+ _(result).must_equal(%w[ foo bar ])
162
+ end
163
+ end
164
+
165
+ it "should namespace mapped_mget" do
166
+ if client.respond_to?(:process, true)
167
+ # Redis < 5.0 uses `#process`
168
+ client.expects(:process).with([[:mget, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit"]]).returns(%w[ foo bar ])
169
+ else
170
+ # Redis 5.x calls `#ensure_connected` (private)
171
+ client.send(:ensure_connected).expects(:call).returns(%w[ foo bar ])
172
+ end
173
+ result = store.mapped_mget "rabbit", "white_rabbit"
174
+ _(result.keys).must_equal %w[ rabbit white_rabbit ]
175
+ _(result["rabbit"]).must_equal "foo"
176
+ _(result["white_rabbit"]).must_equal "bar"
177
+ end
178
+
179
+ it "should namespace expire" do
180
+ client.expects(client_call_method_name).with([:expire, "#{@namespace}:rabbit", 60]).once
181
+ store.expire("rabbit", 60)
182
+ end
183
+
184
+ it "should namespace ttl" do
185
+ client.expects(client_call_method_name).with([:ttl, "#{@namespace}:rabbit"]).once
186
+ store.ttl("rabbit")
187
+ end
188
+
189
+ it "should namespace watch" do
190
+ client.expects(client_call_method_name).with([:watch, "#{@namespace}:rabbit"]).once
191
+ store.watch("rabbit")
192
+ end
193
+
194
+ it "wraps flushdb with appropriate KEYS * calls" do
195
+ client.expects(client_call_method_name).with([:flushdb]).never
196
+ client.expects(client_call_method_name).with([:keys, "#{@namespace}:*"]).once.returns(["rabbit"])
197
+ client.expects(client_call_method_name).with([:del, "#{@namespace}:rabbit"]).once
198
+ store.flushdb
199
+ end
200
+
201
+ it "skips flushdb wrapping if the namespace is nil" do
202
+ client.expects(client_call_method_name).with([:flushdb])
203
+ client.expects(client_call_method_name).with([:keys]).never
204
+ store.with_namespace(nil) do
205
+ store.flushdb
206
+ end
207
+ end
208
+
209
+ it "should namespace hdel" do
210
+ client.expects(client_call_method_name).with([:hdel, "#{@namespace}:rabbit", "key1", "key2"]).once
211
+ store.hdel("rabbit", "key1", "key2")
212
+ end
213
+
214
+ it "should namespace hget" do
215
+ client.expects(client_call_method_name).with([:hget, "#{@namespace}:rabbit", "key"]).once
216
+ store.hget("rabbit", "key")
217
+ end
218
+
219
+ it "should namespace hgetall" do
220
+ client.expects(client_call_method_name).with([:hgetall, "#{@namespace}:rabbit"]).once
221
+ store.hgetall("rabbit")
222
+ end
223
+
224
+ it "should namespace hexists" do
225
+ client.expects(client_call_method_name).with([:hexists, "#{@namespace}:rabbit", "key"]).once
226
+ store.hexists("rabbit", "key")
227
+ end
228
+
229
+ it "should namespace hincrby" do
230
+ client.expects(client_call_method_name).with([:hincrby, "#{@namespace}:rabbit", "key", 1]).once
231
+ store.hincrby("rabbit", "key", 1)
232
+ end
233
+
234
+ it "should namespace hincrbyfloat" do
235
+ client.expects(client_call_method_name).with([:hincrbyfloat, "#{@namespace}:rabbit", "key", 1.5]).once
236
+ store.hincrbyfloat("rabbit", "key", 1.5)
237
+ end
238
+
239
+ it "should namespace hkeys" do
240
+ client.expects(client_call_method_name).with([:hkeys, "#{@namespace}:rabbit"])
241
+ store.hkeys("rabbit")
242
+ end
243
+
244
+ it "should namespace hlen" do
245
+ client.expects(client_call_method_name).with([:hlen, "#{@namespace}:rabbit"])
246
+ store.hlen("rabbit")
247
+ end
248
+
249
+ it "should namespace hmget" do
250
+ client.expects(client_call_method_name).with([:hmget, "#{@namespace}:rabbit", "key1", "key2"])
251
+ store.hmget("rabbit", "key1", "key2")
252
+ end
253
+
254
+ it "should namespace hmset" do
255
+ client.expects(client_call_method_name).with([:hmset, "#{@namespace}:rabbit", "key", @rabbit])
256
+ store.hmset("rabbit", "key", @rabbit)
257
+ end
258
+
259
+ it "should namespace hset" do
260
+ client.expects(client_call_method_name).with([:hset, "#{@namespace}:rabbit", "key", @rabbit])
261
+ store.hset("rabbit", "key", @rabbit)
262
+ end
263
+
264
+ it "should namespace hsetnx" do
265
+ client.expects(client_call_method_name).with([:hsetnx, "#{@namespace}:rabbit", "key", @rabbit])
266
+ store.hsetnx("rabbit", "key", @rabbit)
267
+ end
268
+
269
+ it "should namespace hvals" do
270
+ client.expects(client_call_method_name).with([:hvals, "#{@namespace}:rabbit"])
271
+ store.hvals("rabbit")
272
+ end
273
+
274
+ it "should namespace hscan" do
275
+ client.expects(client_call_method_name).with([:hscan, "#{@namespace}:rabbit", 0])
276
+ store.hscan("rabbit", 0)
277
+ end
278
+
279
+ it "should namespace hscan_each with block" do
280
+ client.public_send(client_call_method_name, [:hset, "#{@namespace}:rabbit", "key1", @rabbit])
281
+ client.expects(client_call_method_name).with([:hscan, "#{@namespace}:rabbit", 0]).returns(["0", ["key1"]])
282
+ results = []
283
+ store.hscan_each("rabbit") do |key|
284
+ results << key
285
+ end
286
+ _(results).must_equal(["key1"])
287
+ end
288
+
289
+ it "should namespace hscan_each without block" do
290
+ client.public_send(client_call_method_name, [:hset, "#{@namespace}:rabbit", "key1", @rabbit])
291
+ client.expects(client_call_method_name).with([:hscan, "#{@namespace}:rabbit", 0]).returns(["0", ["key1"]])
292
+ results = store.hscan_each("rabbit").to_a
293
+ _(results).must_equal(["key1"])
294
+ end
295
+
296
+ it "should namespace zincrby" do
297
+ client.expects(client_call_method_name).with([:zincrby, "#{@namespace}:rabbit", 1.0, "member"])
298
+ store.zincrby("rabbit", 1.0, "member")
299
+ end
300
+
301
+ it "should namespace zscore" do
302
+ client.expects(client_call_method_name).with([:zscore, "#{@namespace}:rabbit", "member"])
303
+ store.zscore("rabbit", "member")
304
+ end
305
+
306
+ it "should namespace zadd" do
307
+ client.expects(client_call_method_name).with([:zadd, "#{@namespace}:rabbit", 1.0, "member"])
308
+ store.zadd("rabbit", 1.0, "member")
309
+ end
310
+
311
+ it "should namespace zrem" do
312
+ client.expects(client_call_method_name).with([:zrem, "#{@namespace}:rabbit", "member"])
313
+ store.zrem("rabbit", "member")
314
+ end
315
+ end
316
+ end
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ describe "Redis::RedisVersion" do
4
+ def setup
5
+ @store = Redis::Store.new
6
+ end
7
+
8
+ def teardown
9
+ @store.quit
10
+ end
11
+
12
+ describe '#redis_version' do
13
+ it 'returns redis version' do
14
+ _(@store.redis_version.to_s).must_match(/^\d{1}\.\d{1,}\.\d{1,}$/)
15
+ end
16
+ end
17
+
18
+ describe '#supports_redis_version?' do
19
+ it 'returns true if redis version is greater or equal to required version' do
20
+ @store.stubs(:redis_version).returns('2.8.19')
21
+ _(@store.supports_redis_version?('2.6.0')).must_equal(true)
22
+ _(@store.supports_redis_version?('2.8.19')).must_equal(true)
23
+ _(@store.supports_redis_version?('2.8.20')).must_equal(false)
24
+ _(@store.supports_redis_version?('2.9.0')).must_equal(false)
25
+ _(@store.supports_redis_version?('3.0.0')).must_equal(false)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,173 @@
1
+ require 'test_helper'
2
+
3
+ describe "Redis::Serialization" do
4
+ def setup
5
+ @store = Redis::Store.new serializer: Marshal
6
+ @rabbit = OpenStruct.new :name => "bunny"
7
+ @white_rabbit = OpenStruct.new :color => "white"
8
+ @store.set "rabbit", @rabbit
9
+ @store.del "rabbit2"
10
+ end
11
+
12
+ def teardown
13
+ @store.flushdb
14
+ @store.quit
15
+ end
16
+
17
+ it "unmarshals on get" do
18
+ _(@store.get("rabbit")).must_equal(@rabbit)
19
+ end
20
+
21
+ it "marshals on set" do
22
+ @store.set "rabbit", @white_rabbit
23
+ _(@store.get("rabbit")).must_equal(@white_rabbit)
24
+ end
25
+
26
+ it "marshals on multi set" do
27
+ @store.mset("rabbit", @white_rabbit, "rabbit2", @rabbit)
28
+ _(@store.get("rabbit")).must_equal(@white_rabbit)
29
+ _(@store.get("rabbit2")).must_equal(@rabbit)
30
+ end
31
+
32
+ if RUBY_VERSION.match(/1\.9/)
33
+ it "doesn't unmarshal on get if raw option is true" do
34
+ _(@store.get("rabbit", :raw => true)).must_equal("\x04\bU:\x0FOpenStruct{\x06:\tnameI\"\nbunny\x06:\x06EF")
35
+ end
36
+ else
37
+ it "doesn't unmarshal on get if raw option is true" do
38
+ _(@store.get("rabbit", :raw => true)).must_include("\x04\bU:\x0FOpenStruct{\x06:\tname")
39
+ end
40
+ end
41
+
42
+ it "doesn't marshal set if raw option is true" do
43
+ @store.set "rabbit", @white_rabbit, :raw => true
44
+ _(@store.get("rabbit", :raw => true)).must_equal(%(#<OpenStruct color="white">))
45
+ end
46
+
47
+ it "doesn't marshal multi set if raw option is true" do
48
+ @store.mset("rabbit", @white_rabbit, "rabbit2", @rabbit, :raw => true)
49
+ _(@store.get("rabbit", :raw => true)).must_equal(%(#<OpenStruct color="white">))
50
+ _(@store.get("rabbit2", :raw => true)).must_equal(%(#<OpenStruct name="bunny">))
51
+ end
52
+
53
+ it "doesn't unmarshal if get returns an empty string" do
54
+ @store.set "empty_string", ""
55
+ _(@store.get("empty_string")).must_equal("")
56
+ # TODO use a meaningful Exception
57
+ # lambda { @store.get("empty_string").must_equal("") }.wont_raise Exception
58
+ end
59
+
60
+ it "doesn't set an object if already exist" do
61
+ @store.setnx "rabbit", @white_rabbit
62
+ _(@store.get("rabbit")).must_equal(@rabbit)
63
+ end
64
+
65
+ it "marshals on set unless exists" do
66
+ @store.setnx "rabbit2", @white_rabbit
67
+ _(@store.get("rabbit2")).must_equal(@white_rabbit)
68
+ end
69
+
70
+ it "doesn't marshal on set unless exists if raw option is true" do
71
+ @store.setnx "rabbit2", @white_rabbit, :raw => true
72
+ _(@store.get("rabbit2", :raw => true)).must_equal(%(#<OpenStruct color="white">))
73
+ end
74
+
75
+ it "marshals on set expire" do
76
+ @store.setex "rabbit2", 1, @white_rabbit
77
+ _(@store.get("rabbit2")).must_equal(@white_rabbit)
78
+ sleep 2
79
+ _(@store.get("rabbit2")).must_be_nil
80
+ end
81
+
82
+ unless ENV['CI']
83
+ it "marshals setex (over a distributed store)" do
84
+ @store = Redis::DistributedStore.new [
85
+ { :host => "localhost", :port => "6380", :db => 0 },
86
+ { :host => "localhost", :port => "6381", :db => 0 }
87
+ ]
88
+ @store.setex "rabbit", 50, @white_rabbit
89
+ _(@store.get("rabbit")).must_equal(@white_rabbit)
90
+ end
91
+
92
+ it "doesn't marshal setex if raw option is true (over a distributed store)" do
93
+ @store = Redis::DistributedStore.new [
94
+ { :host => "localhost", :port => "6380", :db => 0 },
95
+ { :host => "localhost", :port => "6381", :db => 0 }
96
+ ]
97
+ @store.setex "rabbit", 50, @white_rabbit, :raw => true
98
+ _(@store.get("rabbit", :raw => true)).must_equal(%(#<OpenStruct color="white">))
99
+ end
100
+ end
101
+
102
+ it "unmarshals on multi get" do
103
+ @store.set "rabbit2", @white_rabbit
104
+ @store.mget "rabbit", "rabbit2" do |rabbits|
105
+ rabbit, rabbit2 = rabbits
106
+ _(rabbits.length).must_equal(2)
107
+ _(rabbit).must_equal(@rabbit)
108
+ _(rabbit2).must_equal(@white_rabbit)
109
+ end
110
+ end
111
+
112
+ it "unmarshals on mapped_mget" do
113
+ @store.set "rabbit2", @white_rabbit
114
+ result = @store.mapped_mget("rabbit", "rabbit2")
115
+ _(result.keys).must_equal %w[ rabbit rabbit2 ]
116
+ _(result["rabbit"]).must_equal @rabbit
117
+ _(result["rabbit2"]).must_equal @white_rabbit
118
+ end
119
+
120
+ if RUBY_VERSION.match(/1\.9/)
121
+ it "doesn't unmarshal on multi get if raw option is true" do
122
+ @store.set "rabbit2", @white_rabbit
123
+ @store.mget "rabbit", "rabbit2", :raw => true do |rabbit, rabbit2|
124
+ _(rabbit).must_equal("\x04\bU:\x0FOpenStruct{\x06:\tnameI\"\nbunny\x06:\x06EF")
125
+ _(rabbit2).must_equal("\x04\bU:\x0FOpenStruct{\x06:\ncolorI\"\nwhite\x06:\x06EF")
126
+ end
127
+ end
128
+ else
129
+ it "doesn't unmarshal on multi get if raw option is true" do
130
+ @store.set "rabbit2", @white_rabbit
131
+ @store.mget "rabbit", "rabbit2", :raw => true do |rabbit, rabbit2|
132
+ _(rabbit).must_include("\x04\bU:\x0FOpenStruct{\x06:\tname")
133
+ _(rabbit2).must_include("\x04\bU:\x0FOpenStruct{\x06:\ncolor")
134
+ end
135
+ end
136
+ end
137
+
138
+ describe "binary safety" do
139
+ it "marshals objects" do
140
+ utf8_key = [51339].pack("U*")
141
+ ascii_rabbit = OpenStruct.new(:name => [128].pack("C*"))
142
+
143
+ @store.set(utf8_key, ascii_rabbit)
144
+ _(@store.get(utf8_key)).must_equal(ascii_rabbit)
145
+ end
146
+
147
+ it "gets and sets raw values" do
148
+ utf8_key = [51339].pack("U*")
149
+ ascii_string = [128].pack("C*")
150
+
151
+ @store.set(utf8_key, ascii_string, :raw => true)
152
+ _(@store.get(utf8_key, :raw => true).bytes.to_a).must_equal(ascii_string.bytes.to_a)
153
+ end
154
+
155
+ it "marshals objects on setnx" do
156
+ utf8_key = [51339].pack("U*")
157
+ ascii_rabbit = OpenStruct.new(:name => [128].pack("C*"))
158
+
159
+ @store.del(utf8_key)
160
+ @store.setnx(utf8_key, ascii_rabbit)
161
+ _(@store.get(utf8_key)).must_equal(ascii_rabbit)
162
+ end
163
+
164
+ it "gets and sets raw values on setnx" do
165
+ utf8_key = [51339].pack("U*")
166
+ ascii_string = [128].pack("C*")
167
+
168
+ @store.del(utf8_key)
169
+ @store.setnx(utf8_key, ascii_string, :raw => true)
170
+ _(@store.get(utf8_key, :raw => true).bytes.to_a).must_equal(ascii_string.bytes.to_a)
171
+ end
172
+ end if defined?(Encoding)
173
+ end
@@ -0,0 +1,142 @@
1
+ require 'test_helper'
2
+
3
+ class MockRedis
4
+ def initialize
5
+ @sets = []
6
+ @setexes = []
7
+ @setnxes = []
8
+ @expires = []
9
+ end
10
+
11
+ def set(*a)
12
+ @sets << a
13
+ end
14
+
15
+ def has_set?(*a)
16
+ @sets.include?(a)
17
+ end
18
+
19
+ def setex(*a)
20
+ @setexes << a
21
+ end
22
+
23
+ def has_setex?(*a)
24
+ @setexes.include?(a)
25
+ end
26
+
27
+ def setnx(*a)
28
+ @setnxes << a
29
+ end
30
+
31
+ def has_setnx?(*a)
32
+ @setnxes.include?(a)
33
+ end
34
+
35
+ def multi(&block)
36
+ instance_eval do
37
+ def setnx(*a)
38
+ @setnxes << a
39
+ end
40
+
41
+ block.call(self)
42
+ end
43
+ end
44
+ alias_method :pipelined, :multi
45
+
46
+ def expire(*a)
47
+ @expires << a
48
+ end
49
+
50
+ def has_expire?(*a)
51
+ @expires.include?(a)
52
+ end
53
+ end
54
+
55
+ class MockTtlStore < MockRedis
56
+ include Redis::Store::Ttl
57
+ end
58
+
59
+ describe MockTtlStore do
60
+ let(:key) { 'hello' }
61
+ let(:mock_value) { 'value' }
62
+ let(:options) { { :expire_after => 3600 } }
63
+ let(:redis) { MockTtlStore.new }
64
+
65
+ describe '#set' do
66
+ describe 'without options' do
67
+ it 'must call super with key and value' do
68
+ redis.set(key, mock_value)
69
+ _(redis.has_set?(key, mock_value, nil)).must_equal true
70
+ end
71
+ end
72
+
73
+ describe 'with options' do
74
+ it 'must call setex with proper expiry and set raw to true' do
75
+ redis.set(key, mock_value, options)
76
+ _(redis.has_setex?(key, options[:expire_after], mock_value, :raw => true)).must_equal true
77
+ end
78
+ end
79
+
80
+ describe 'with nx and ex option' do
81
+ it 'must call super with key and value and options' do
82
+ set_options = { nx: true, ex: 3600 }
83
+ redis.set(key, mock_value, set_options)
84
+ _(redis.has_set?(key, mock_value, set_options)).must_equal true
85
+ end
86
+ end
87
+ end
88
+
89
+ describe '#setnx' do
90
+ describe 'without expiry' do
91
+ it 'must call super with key and value' do
92
+ redis.setnx(key, mock_value)
93
+ redis.has_setnx?(key, mock_value)
94
+ end
95
+
96
+ it 'must not call expire' do
97
+ redis.expects(:expire).never
98
+ redis.setnx(key, mock_value)
99
+ end
100
+ end
101
+
102
+ describe 'with expiry' do
103
+ it 'uses the mutli command to chain commands' do
104
+ redis.expects(:multi)
105
+ redis.setnx(key, mock_value, options)
106
+ end
107
+
108
+ it 'must call expire' do
109
+ redis.setnx(key, mock_value, options)
110
+ _(redis.has_expire?(key, options[:expire_after])).must_equal true
111
+ end
112
+
113
+ describe 'avoiding multi commands' do
114
+ let(:options) { { :expire_after => 3600, :avoid_multi_commands => true } }
115
+
116
+ it 'uses the redis pipelined feature to chain commands' do
117
+ redis.expects(:pipelined)
118
+ redis.setnx(key, mock_value, options)
119
+ end
120
+
121
+ it 'must call expire' do
122
+ redis.setnx(key, mock_value, options)
123
+ _(redis.has_expire?(key, options[:expire_after])).must_equal true
124
+ end
125
+ end
126
+
127
+ describe 'using a redis cluster' do
128
+ let(:options) { { :expire_after => 3600, :cluster => %w[redis://127.0.0.1:6379/0] } }
129
+
130
+ it 'uses the redis pipelined feature to chain commands' do
131
+ redis.expects(:pipelined)
132
+ redis.setnx(key, mock_value, options)
133
+ end
134
+
135
+ it 'must call expire' do
136
+ redis.setnx(key, mock_value, options)
137
+ _(redis.has_expire?(key, options[:expire_after])).must_equal true
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ describe Redis::Store::VERSION do
4
+ it 'returns current version' do
5
+ _(Redis::Store::VERSION).wont_equal nil
6
+ end
7
+ end