hoodoo 1.13.0 → 1.14.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 +4 -4
- data/lib/hoodoo.rb +1 -0
- data/lib/hoodoo/services/services/session.rb +8 -104
- data/lib/hoodoo/transient_store.rb +19 -0
- data/lib/hoodoo/transient_store/mocks/dalli_client.rb +148 -0
- data/lib/hoodoo/transient_store/mocks/redis.rb +138 -0
- data/lib/hoodoo/transient_store/transient_store.rb +344 -0
- data/lib/hoodoo/transient_store/transient_store/base.rb +81 -0
- data/lib/hoodoo/transient_store/transient_store/memcached.rb +116 -0
- data/lib/hoodoo/transient_store/transient_store/memcached_redis_mirror.rb +181 -0
- data/lib/hoodoo/transient_store/transient_store/redis.rb +126 -0
- data/lib/hoodoo/version.rb +1 -1
- data/spec/active/active_record/support_spec.rb +3 -9
- data/spec/active/active_record/translated_spec.rb +2 -5
- data/spec/logger/writers/file_writer_spec.rb +1 -4
- data/spec/logger/writers/stream_writer_spec.rb +2 -9
- data/spec/services/middleware/middleware_logging_spec.rb +1 -4
- data/spec/services/middleware/middleware_permissions_spec.rb +2 -2
- data/spec/services/services/interface_spec.rb +2 -2
- data/spec/services/services/session_spec.rb +26 -19
- data/spec/transient_store/transient_store/base_spec.rb +52 -0
- data/spec/transient_store/transient_store/memcached_redis_mirror_spec.rb +380 -0
- data/spec/transient_store/transient_store/memcached_spec.rb +244 -0
- data/spec/transient_store/transient_store/mocks/dalli_client_spec.rb +44 -0
- data/spec/transient_store/transient_store/mocks/redis_spec.rb +28 -0
- data/spec/transient_store/transient_store/redis_spec.rb +242 -0
- data/spec/transient_store/transient_store_spec.rb +448 -0
- metadata +31 -9
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'dalli'
|
4
|
+
require 'hoodoo/transient_store/mocks/dalli_client'
|
5
|
+
|
6
|
+
# ============================================================================
|
7
|
+
|
8
|
+
old_level = Dalli.logger.level
|
9
|
+
Dalli.logger.level = Logger::ERROR
|
10
|
+
client = ::Dalli::Client.new( 'localhost:11211' )
|
11
|
+
result = client.stats() rescue nil
|
12
|
+
Dalli.logger.level = old_level
|
13
|
+
$memcached_missing = result.is_a?( Hash ) == false || result[ 'localhost:11211' ].nil?
|
14
|
+
|
15
|
+
backends = [ :mock ]
|
16
|
+
backends << :real unless $memcached_missing
|
17
|
+
|
18
|
+
# ============================================================================
|
19
|
+
|
20
|
+
describe Hoodoo::TransientStore::Memcached do
|
21
|
+
before :all do
|
22
|
+
@old_level = Dalli.logger.level
|
23
|
+
Dalli.logger.level = Logger::ERROR
|
24
|
+
end
|
25
|
+
|
26
|
+
after :all do
|
27
|
+
Dalli.logger.level = @old_level
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'registers itself' do
|
31
|
+
expect( Hoodoo::TransientStore.supported_storage_engines() ).to include( :memcached )
|
32
|
+
end
|
33
|
+
|
34
|
+
if $memcached_missing
|
35
|
+
pending "*** WARNING *** Memcached not present on 'localhost:11211', cannot test real engine"
|
36
|
+
end
|
37
|
+
|
38
|
+
shared_examples 'a Memcached abstraction' do | backend |
|
39
|
+
|
40
|
+
# Either expect something on the known mock backend instance or an unknown
|
41
|
+
# (any) real Dalli::Client instance. Can then call "to" - i.e. use:
|
42
|
+
#
|
43
|
+
# expect_dalli_client( backend ).to...
|
44
|
+
#
|
45
|
+
# +backend+:: Pass either Symbol ":mock" or ":real".
|
46
|
+
#
|
47
|
+
def expect_dalli_client( backend )
|
48
|
+
return case backend
|
49
|
+
when :mock
|
50
|
+
expect( @mock_dalli_client_instance )
|
51
|
+
else
|
52
|
+
expect_any_instance_of( ::Dalli::Client )
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# ========================================================================
|
57
|
+
|
58
|
+
before :each do
|
59
|
+
@storage_engine_uri = 'localhost:11211'
|
60
|
+
@namespace = Hoodoo::UUID.generate()
|
61
|
+
|
62
|
+
if backend == :mock
|
63
|
+
Hoodoo::TransientStore::Mocks::DalliClient.reset()
|
64
|
+
@mock_dalli_client_instance = Hoodoo::TransientStore::Mocks::DalliClient.new
|
65
|
+
|
66
|
+
expect( ::Dalli::Client ).to(
|
67
|
+
receive( :new ).
|
68
|
+
with(
|
69
|
+
@storage_engine_uri,
|
70
|
+
hash_including( { :namespace => @namespace } )
|
71
|
+
).
|
72
|
+
and_return( @mock_dalli_client_instance )
|
73
|
+
)
|
74
|
+
else
|
75
|
+
expect( ::Dalli::Client ).to(
|
76
|
+
receive( :new ).
|
77
|
+
with(
|
78
|
+
@storage_engine_uri,
|
79
|
+
hash_including( { :namespace => @namespace } )
|
80
|
+
).
|
81
|
+
and_call_original()
|
82
|
+
)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# ========================================================================
|
87
|
+
|
88
|
+
context "#initialize (#{ backend })" do
|
89
|
+
it 'initialises' do
|
90
|
+
instance = Hoodoo::TransientStore::Memcached.new(
|
91
|
+
storage_host_uri: @storage_engine_uri,
|
92
|
+
namespace: @namespace
|
93
|
+
)
|
94
|
+
|
95
|
+
expect( instance ).to be_a( Hoodoo::TransientStore::Memcached )
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'complains about strange Memcached behaviour' do
|
99
|
+
expect_dalli_client( backend ).to receive( :stats ).and_return( nil )
|
100
|
+
|
101
|
+
expect {
|
102
|
+
instance = Hoodoo::TransientStore::Memcached.new(
|
103
|
+
storage_host_uri: @storage_engine_uri,
|
104
|
+
namespace: @namespace
|
105
|
+
)
|
106
|
+
}.to raise_error(
|
107
|
+
RuntimeError,
|
108
|
+
"Hoodoo::TransientStore::Memcached: Did not get back meaningful data from Memcached at '#{ @storage_engine_uri }'"
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'handles exceptions' do
|
113
|
+
expect_dalli_client( backend ).to receive( :stats ).and_raise( 'Hello world' )
|
114
|
+
|
115
|
+
expect {
|
116
|
+
instance = Hoodoo::TransientStore::Memcached.new(
|
117
|
+
storage_host_uri: @storage_engine_uri,
|
118
|
+
namespace: @namespace
|
119
|
+
)
|
120
|
+
}.to raise_error(
|
121
|
+
RuntimeError,
|
122
|
+
"Hoodoo::TransientStore::Memcached: Cannot connect to Memcached at '#{ @storage_engine_uri }': Hello world"
|
123
|
+
)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# ========================================================================
|
128
|
+
|
129
|
+
context "when initialised (#{ backend })" do
|
130
|
+
before :each do
|
131
|
+
@instance = Hoodoo::TransientStore::Memcached.new(
|
132
|
+
storage_host_uri: @storage_engine_uri,
|
133
|
+
namespace: @namespace
|
134
|
+
)
|
135
|
+
|
136
|
+
@key = Hoodoo::UUID.generate()
|
137
|
+
@payload = { 'bar' => 'baz' }
|
138
|
+
@ttl = 120
|
139
|
+
end
|
140
|
+
|
141
|
+
context '#set' do
|
142
|
+
it 'sets' do
|
143
|
+
expect_dalli_client( backend ).to receive( :set ).with( @key, @payload, @ttl ).and_call_original()
|
144
|
+
|
145
|
+
result = @instance.set(
|
146
|
+
key: @key,
|
147
|
+
payload: @payload,
|
148
|
+
maximum_lifespan: @ttl
|
149
|
+
)
|
150
|
+
|
151
|
+
expect( result ).to eq( true )
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'allows exceptions to propagate' do
|
155
|
+
expect_dalli_client( backend ).to receive( :set ).with( @key, @payload, @ttl ).and_raise( 'Hello world' )
|
156
|
+
|
157
|
+
expect {
|
158
|
+
@instance.set(
|
159
|
+
key: @key,
|
160
|
+
payload: @payload,
|
161
|
+
maximum_lifespan: @ttl
|
162
|
+
)
|
163
|
+
}.to raise_error( RuntimeError, "Hello world" )
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context '#get' do
|
168
|
+
before :each do
|
169
|
+
expect_dalli_client( backend ).to receive( :set ).with( @key, @payload, @ttl ).and_call_original()
|
170
|
+
|
171
|
+
@instance.set(
|
172
|
+
key: @key,
|
173
|
+
payload: @payload,
|
174
|
+
maximum_lifespan: @ttl
|
175
|
+
)
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'gets known keys' do
|
179
|
+
expect_dalli_client( backend ).to receive( :get ).with( @key ).and_call_original()
|
180
|
+
expect( @instance.get( key: @key ) ).to eql( @payload )
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'returns "nil" for unknown keys' do
|
184
|
+
expect( @instance.get( key: Hoodoo::UUID.generate() ) ).to be_nil
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'allows exceptions to propagate' do
|
188
|
+
expect_dalli_client( backend ).to receive( :get ).with( @key ).and_raise( 'Hello world' )
|
189
|
+
|
190
|
+
expect {
|
191
|
+
@instance.get( key: @key )
|
192
|
+
}.to raise_error( RuntimeError, "Hello world" )
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context '#delete' do
|
197
|
+
before :each do
|
198
|
+
expect_dalli_client( backend ).to receive( :set ).with( @key, @payload, @ttl ).and_call_original()
|
199
|
+
|
200
|
+
@instance.set(
|
201
|
+
key: @key,
|
202
|
+
payload: @payload,
|
203
|
+
maximum_lifespan: @ttl
|
204
|
+
)
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'deletes known keys' do
|
208
|
+
expect( @instance.get( key: @key ) ).to eql( @payload )
|
209
|
+
expect_dalli_client( backend ).to receive( :delete ).with( @key ).and_call_original()
|
210
|
+
|
211
|
+
result = @instance.delete( key: @key )
|
212
|
+
|
213
|
+
expect( result ).to eq( true )
|
214
|
+
expect( @instance.get( key: @key ) ).to eql( nil )
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'ignores unknown keys' do
|
218
|
+
expect( @instance.delete( key: Hoodoo::UUID.generate() ) ).to eql( true )
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'allows exceptions to propagate' do
|
222
|
+
expect_dalli_client( backend ).to receive( :delete ).with( @key ).and_raise( 'Hello world' )
|
223
|
+
|
224
|
+
expect {
|
225
|
+
@instance.delete( key: @key )
|
226
|
+
}.to raise_error( RuntimeError, "Hello world" )
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
context 'close' do
|
231
|
+
it 'closes' do
|
232
|
+
expect_dalli_client( backend ).to receive( :close )
|
233
|
+
@instance.close()
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
end # 'context "when initialised (#{ backend })" do'
|
238
|
+
end # 'shared_examples ...'
|
239
|
+
|
240
|
+
backends.each do | backend |
|
241
|
+
it_behaves_like( 'a Memcached abstraction', backend )
|
242
|
+
end
|
243
|
+
|
244
|
+
end # 'describe...'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Most of the mock client is covered by the TransientStore Memcached layer
|
4
|
+
# tests, which use the mock backend as well as a real one. Tests are implicit.
|
5
|
+
# This file contains any additional coverage not handled in
|
6
|
+
# transient_store/transient_store/memcached_spec.rb already.
|
7
|
+
#
|
8
|
+
describe Hoodoo::TransientStore::Mocks::DalliClient do
|
9
|
+
|
10
|
+
context 'sanctioned and maintained method' do
|
11
|
+
it '::store() returns the data store' do
|
12
|
+
Hoodoo::TransientStore::Mocks::DalliClient.reset()
|
13
|
+
mock_dalli_client_instance = Hoodoo::TransientStore::Mocks::DalliClient.new
|
14
|
+
mock_dalli_client_instance.set( 'foo', 'bar' )
|
15
|
+
expect( Hoodoo::TransientStore::Mocks::DalliClient.store ).to have_key( 'foo' )
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# ==========================================================================
|
20
|
+
|
21
|
+
context 'deprecated but indefinitely maintained method' do
|
22
|
+
|
23
|
+
# Chicken and egg - we need to use the methods we're going to test in the
|
24
|
+
# test setup to avoid breaking or being broken by prior test execution!
|
25
|
+
|
26
|
+
before :all do
|
27
|
+
@old_bypass = Hoodoo::TransientStore::Mocks::DalliClient.bypass?
|
28
|
+
Hoodoo::TransientStore::Mocks::DalliClient.bypass( false )
|
29
|
+
end
|
30
|
+
|
31
|
+
after :all do
|
32
|
+
Hoodoo::TransientStore::Mocks::DalliClient.bypass( @old_bypass )
|
33
|
+
end
|
34
|
+
|
35
|
+
it '::bypass=(...) sets and ::bypass?() reads the "bypass" flag' do
|
36
|
+
Hoodoo::TransientStore::Mocks::DalliClient.bypass( true )
|
37
|
+
expect( Hoodoo::TransientStore::Mocks::DalliClient.bypass? ).to eql( true )
|
38
|
+
|
39
|
+
Hoodoo::TransientStore::Mocks::DalliClient.bypass( false )
|
40
|
+
expect( Hoodoo::TransientStore::Mocks::DalliClient.bypass? ).to eql( false )
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Most of the mock client is covered by the TransientStore Redis layer tests,
|
4
|
+
# which use the mock backend as well as a real one. Tests are implicit. This
|
5
|
+
# file contains any additional coverage not handled in
|
6
|
+
# transient_store/transient_store/redis_spec.rb already.
|
7
|
+
#
|
8
|
+
describe Hoodoo::TransientStore::Mocks::Redis do
|
9
|
+
|
10
|
+
context 'sanctioned and maintained method' do
|
11
|
+
it '::store() returns the data store' do
|
12
|
+
Hoodoo::TransientStore::Mocks::Redis.reset()
|
13
|
+
mock_redis_instance = Hoodoo::TransientStore::Mocks::Redis.new
|
14
|
+
mock_redis_instance.set( 'foo', 'bar' )
|
15
|
+
expect( Hoodoo::TransientStore::Mocks::Redis.store ).to have_key( 'foo' )
|
16
|
+
end
|
17
|
+
|
18
|
+
it '#expire(...) raises an error for attempts to expire bad keys' do
|
19
|
+
mock_redis_instance = Hoodoo::TransientStore::Mocks::Redis.new
|
20
|
+
key = Hoodoo::UUID.generate()
|
21
|
+
|
22
|
+
expect {
|
23
|
+
mock_redis_instance.expire( key, 60 )
|
24
|
+
}.to raise_error( RuntimeError, "Hoodoo::TransientStore::Mocks::Redis\#expire: Cannot find key '#{ key }'" )
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'redis'
|
4
|
+
require 'hoodoo/transient_store/mocks/redis'
|
5
|
+
|
6
|
+
# ============================================================================
|
7
|
+
|
8
|
+
client = ::Redis.new( :url => 'redis://localhost:6379' )
|
9
|
+
result = client.info( 'CPU' ) rescue nil
|
10
|
+
|
11
|
+
$redis_missing = result.is_a?( Hash ) == false
|
12
|
+
|
13
|
+
backends = [ :mock ]
|
14
|
+
backends << :real unless $redis_missing
|
15
|
+
|
16
|
+
# ============================================================================
|
17
|
+
|
18
|
+
describe Hoodoo::TransientStore::Redis do
|
19
|
+
|
20
|
+
it 'registers itself' do
|
21
|
+
expect( Hoodoo::TransientStore.supported_storage_engines() ).to include( :redis )
|
22
|
+
end
|
23
|
+
|
24
|
+
if $redis_missing
|
25
|
+
pending "*** WARNING *** Redis not present on 'redis://localhost:6379', cannot test real engine"
|
26
|
+
end
|
27
|
+
|
28
|
+
shared_examples 'a Redis abstraction' do | backend |
|
29
|
+
|
30
|
+
# Either expect something on the known mock Redis instance, or an unknown
|
31
|
+
# (any) real Redis instance. Can then call "to" - i.e. use:
|
32
|
+
#
|
33
|
+
# expect_redis( backend ).to...
|
34
|
+
#
|
35
|
+
# +backend+:: Pass either Symbol ":mock" or ":real".
|
36
|
+
#
|
37
|
+
def expect_redis( backend )
|
38
|
+
return case backend
|
39
|
+
when :mock
|
40
|
+
expect( @mock_redis_instance )
|
41
|
+
else
|
42
|
+
expect_any_instance_of( ::Redis )
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# ========================================================================
|
47
|
+
|
48
|
+
before :each do
|
49
|
+
@storage_engine_uri = 'redis://localhost:6379'
|
50
|
+
@namespace = Hoodoo::UUID.generate()
|
51
|
+
|
52
|
+
if backend == :mock
|
53
|
+
Hoodoo::TransientStore::Mocks::Redis.reset()
|
54
|
+
@mock_redis_instance = Hoodoo::TransientStore::Mocks::Redis.new
|
55
|
+
|
56
|
+
expect( ::Redis ).to(
|
57
|
+
receive( :new ).
|
58
|
+
with( hash_including( { :url => @storage_engine_uri } ) ).
|
59
|
+
and_return( @mock_redis_instance )
|
60
|
+
)
|
61
|
+
else
|
62
|
+
expect( ::Redis ).to(
|
63
|
+
receive( :new ).
|
64
|
+
with( hash_including( { :url => @storage_engine_uri } ) ).
|
65
|
+
and_call_original()
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# ========================================================================
|
71
|
+
|
72
|
+
context "#initialize (#{ backend })" do
|
73
|
+
it 'initialises' do
|
74
|
+
instance = Hoodoo::TransientStore::Redis.new(
|
75
|
+
storage_host_uri: @storage_engine_uri,
|
76
|
+
namespace: @namespace
|
77
|
+
)
|
78
|
+
|
79
|
+
expect( instance ).to be_a( Hoodoo::TransientStore::Redis )
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'complains about strange Redis behaviour' do
|
83
|
+
expect_redis( backend ).to receive( :info ).and_return( nil )
|
84
|
+
|
85
|
+
expect {
|
86
|
+
instance = Hoodoo::TransientStore::Redis.new(
|
87
|
+
storage_host_uri: @storage_engine_uri,
|
88
|
+
namespace: @namespace
|
89
|
+
)
|
90
|
+
}.to raise_error(
|
91
|
+
RuntimeError,
|
92
|
+
"Hoodoo::TransientStore::Redis: Did not get back meaningful data from Redis at '#{ @storage_engine_uri }'"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'handles exceptions' do
|
97
|
+
expect_redis( backend ).to receive( :info ).and_raise( 'Hello world' )
|
98
|
+
|
99
|
+
expect {
|
100
|
+
instance = Hoodoo::TransientStore::Redis.new(
|
101
|
+
storage_host_uri: @storage_engine_uri,
|
102
|
+
namespace: @namespace
|
103
|
+
)
|
104
|
+
}.to raise_error(
|
105
|
+
RuntimeError,
|
106
|
+
"Hoodoo::TransientStore::Redis: Cannot connect to Redis at '#{ @storage_engine_uri }': Hello world"
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'generates expected namespaced keys' do
|
111
|
+
instance = Hoodoo::TransientStore::Redis.new(
|
112
|
+
storage_host_uri: @storage_engine_uri,
|
113
|
+
namespace: @namespace
|
114
|
+
)
|
115
|
+
|
116
|
+
expect( instance.send( :namespaced_key, 'foo' ) ).to eql( "#{ @namespace }foo" )
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# ========================================================================
|
121
|
+
|
122
|
+
context "when initialised (#{ backend })" do
|
123
|
+
before :each do
|
124
|
+
@instance = Hoodoo::TransientStore::Redis.new(
|
125
|
+
storage_host_uri: @storage_engine_uri,
|
126
|
+
namespace: @namespace
|
127
|
+
)
|
128
|
+
|
129
|
+
@key = Hoodoo::UUID.generate()
|
130
|
+
@nskey = @instance.send( :namespaced_key, @key )
|
131
|
+
@payload = { 'bar' => 'baz' }
|
132
|
+
@jpayload = JSON.fast_generate( @payload )
|
133
|
+
@ttl = 120
|
134
|
+
end
|
135
|
+
|
136
|
+
context '#set' do
|
137
|
+
it 'sets' do
|
138
|
+
expect_redis( backend ).to receive( :[]= ).with( @nskey, @jpayload ).and_call_original()
|
139
|
+
expect_redis( backend ).to receive( :expire ).with( @nskey, @ttl ).and_call_original()
|
140
|
+
|
141
|
+
result = @instance.set(
|
142
|
+
key: @key,
|
143
|
+
payload: @payload,
|
144
|
+
maximum_lifespan: @ttl
|
145
|
+
)
|
146
|
+
|
147
|
+
expect( result ).to eq( true )
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'allows exceptions to propagate' do
|
151
|
+
expect_redis( backend ).to receive( :[]= ).with( @nskey, @jpayload ).and_raise( 'Hello world' )
|
152
|
+
|
153
|
+
expect {
|
154
|
+
@instance.set(
|
155
|
+
key: @key,
|
156
|
+
payload: @payload,
|
157
|
+
maximum_lifespan: @ttl
|
158
|
+
)
|
159
|
+
}.to raise_error( RuntimeError, "Hello world" )
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context '#get' do
|
164
|
+
before :each do
|
165
|
+
expect_redis( backend ).to receive( :[]= ).with( @nskey, @jpayload ).and_call_original()
|
166
|
+
expect_redis( backend ).to receive( :expire ).with( @nskey, @ttl ).and_call_original()
|
167
|
+
|
168
|
+
@instance.set(
|
169
|
+
key: @key,
|
170
|
+
payload: @payload,
|
171
|
+
maximum_lifespan: @ttl
|
172
|
+
)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'gets known keys' do
|
176
|
+
expect_redis( backend ).to receive( :[] ).with( @nskey ).and_call_original()
|
177
|
+
expect( @instance.get( key: @key ) ).to eql( @payload )
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'returns "nil" for unknown keys' do
|
181
|
+
expect( @instance.get( key: Hoodoo::UUID.generate() ) ).to be_nil
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'allows exceptions to propagate' do
|
185
|
+
expect_redis( backend ).to receive( :[] ).with( @nskey ).and_raise( 'Hello world' )
|
186
|
+
|
187
|
+
expect {
|
188
|
+
@instance.get( key: @key )
|
189
|
+
}.to raise_error( RuntimeError, "Hello world" )
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context '#delete' do
|
194
|
+
before :each do
|
195
|
+
expect_redis( backend ).to receive( :[]= ).with( @nskey, @jpayload ).and_call_original()
|
196
|
+
expect_redis( backend ).to receive( :expire ).with( @nskey, @ttl ).and_call_original()
|
197
|
+
|
198
|
+
@instance.set(
|
199
|
+
key: @key,
|
200
|
+
payload: @payload,
|
201
|
+
maximum_lifespan: @ttl
|
202
|
+
)
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'deletes known keys' do
|
206
|
+
expect( @instance.get( key: @key ) ).to eql( @payload )
|
207
|
+
expect_redis( backend ).to receive( :del ).with( @nskey ).and_call_original()
|
208
|
+
|
209
|
+
result = @instance.delete( key: @key )
|
210
|
+
|
211
|
+
expect( result ).to eq( true )
|
212
|
+
expect( @instance.get( key: @key ) ).to eql( nil )
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'ignores unknown keys' do
|
216
|
+
expect( @instance.delete( key: Hoodoo::UUID.generate() ) ).to eql( true )
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'allows exceptions to propagate' do
|
220
|
+
expect_redis( backend ).to receive( :del ).with( @nskey ).and_raise( 'Hello world' )
|
221
|
+
|
222
|
+
expect {
|
223
|
+
@instance.delete( key: @key )
|
224
|
+
}.to raise_error( RuntimeError, "Hello world" )
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
context 'close' do
|
229
|
+
it 'closes' do
|
230
|
+
expect_redis( backend ).to receive( :quit )
|
231
|
+
@instance.close()
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
end # 'context "when initialised (#{ backend })" do'
|
236
|
+
end # 'shared_examples ...'
|
237
|
+
|
238
|
+
backends.each do | backend |
|
239
|
+
it_behaves_like( 'a Redis abstraction', backend )
|
240
|
+
end
|
241
|
+
|
242
|
+
end # 'describe...'
|