redis-store-pika 1.9.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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