hoodoo 1.14.0 → 1.15.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/services/middleware/endpoints/inter_resource_remote.rb +1 -1
- data/lib/hoodoo/services/middleware/middleware.rb +2 -2
- data/lib/hoodoo/services/services/session.rb +205 -144
- data/lib/hoodoo/transient_store/transient_store.rb +13 -4
- data/lib/hoodoo/transient_store/transient_store/memcached.rb +8 -0
- data/lib/hoodoo/version.rb +1 -1
- data/spec/active/active_record/finder_spec.rb +4 -4
- data/spec/client/client_spec.rb +4 -0
- data/spec/services/middleware/middleware_permissions_spec.rb +28 -32
- data/spec/services/services/session_spec.rb +485 -353
- data/spec/spec_helper.rb +31 -10
- data/spec/transient_store/transient_store/memcached_redis_mirror_spec.rb +3 -13
- data/spec/transient_store/transient_store/memcached_spec.rb +15 -0
- data/spec/transient_store/transient_store_spec.rb +11 -1
- metadata +2 -2
@@ -87,7 +87,7 @@ module Hoodoo
|
|
87
87
|
#
|
88
88
|
attr_reader :storage_engine
|
89
89
|
|
90
|
-
# Read the storage engine
|
90
|
+
# Read the storage engine instance for the #storage_engine - this allows
|
91
91
|
# engine-specific configuration to be set where available, though this is
|
92
92
|
# strongly discouraged as it couples client code to the engine in use,
|
93
93
|
# defeating the main rationale behind the TransientStore abstraction.
|
@@ -256,7 +256,11 @@ module Hoodoo
|
|
256
256
|
#
|
257
257
|
# _Named_ parameters are:
|
258
258
|
#
|
259
|
-
# +key+::
|
259
|
+
# +key+:: Key previously given to #set.
|
260
|
+
#
|
261
|
+
# +allow_throw+:: If +true+, exceptions raised by the underlying storage
|
262
|
+
# engine are thrown, else ignored and +nil+ is returned.
|
263
|
+
# Optional; default is +false+.
|
260
264
|
#
|
261
265
|
# Returns +nil+ if the item is not found - either the key is wrong, the
|
262
266
|
# stored data has expired or the stored data has been evicted early from
|
@@ -265,9 +269,14 @@ module Hoodoo
|
|
265
269
|
# Only non-empty String or Symbol keys are permitted, else an exception
|
266
270
|
# will be raised.
|
267
271
|
#
|
268
|
-
def get( key: )
|
272
|
+
def get( key:, allow_throw: false )
|
269
273
|
key = normalise_key( key, 'get' )
|
270
|
-
|
274
|
+
|
275
|
+
begin
|
276
|
+
@storage_engine_instance.get( key: key )
|
277
|
+
rescue
|
278
|
+
raise if allow_throw
|
279
|
+
end
|
271
280
|
end
|
272
281
|
|
273
282
|
# Delete data previously stored with #set.
|
@@ -21,6 +21,14 @@ module Hoodoo
|
|
21
21
|
#
|
22
22
|
class Memcached < Hoodoo::TransientStore::Base
|
23
23
|
|
24
|
+
# Overrideable access to this object's Dalli::Client instance. It is
|
25
|
+
# inadvisable to couple calling code directly into this interface as it
|
26
|
+
# is a Hoodoo::TransientStore::Memcached specialisation, but if deemed
|
27
|
+
# absolutely necessary the Dalli client can be override with a
|
28
|
+
# customised version.
|
29
|
+
#
|
30
|
+
attr_accessor :client
|
31
|
+
|
24
32
|
# See Hoodoo::TransientStore::Base::new for details.
|
25
33
|
#
|
26
34
|
# Do not instantiate this class directly. Use
|
data/lib/hoodoo/version.rb
CHANGED
@@ -309,7 +309,7 @@ describe Hoodoo::ActiveRecord::Finder do
|
|
309
309
|
context 'only makes one database call when' do
|
310
310
|
|
311
311
|
it 'finding on the first attribute' do
|
312
|
-
count =
|
312
|
+
count = spec_helper_count_database_calls_in do
|
313
313
|
found = RSpecModelFinderTest.acquire( @id )
|
314
314
|
expect( found ).to eq(@a)
|
315
315
|
end
|
@@ -318,7 +318,7 @@ describe Hoodoo::ActiveRecord::Finder do
|
|
318
318
|
end
|
319
319
|
|
320
320
|
it 'finding on the second attribute' do
|
321
|
-
count =
|
321
|
+
count = spec_helper_count_database_calls_in do
|
322
322
|
found = RSpecModelFinderTest.acquire( @uuid )
|
323
323
|
expect( found ).to eq(@b)
|
324
324
|
end
|
@@ -327,7 +327,7 @@ describe Hoodoo::ActiveRecord::Finder do
|
|
327
327
|
end
|
328
328
|
|
329
329
|
it 'finding on the third attribute' do
|
330
|
-
count =
|
330
|
+
count = spec_helper_count_database_calls_in do
|
331
331
|
found = RSpecModelFinderTest.acquire( @code )
|
332
332
|
expect( found ).to eq(@c)
|
333
333
|
end
|
@@ -336,7 +336,7 @@ describe Hoodoo::ActiveRecord::Finder do
|
|
336
336
|
end
|
337
337
|
|
338
338
|
it 'checking all three attributes but finding nothing' do
|
339
|
-
count =
|
339
|
+
count = spec_helper_count_database_calls_in do
|
340
340
|
found = RSpecModelFinderTest.acquire( Hoodoo::UUID.generate )
|
341
341
|
expect( found ).to be_nil
|
342
342
|
end
|
data/spec/client/client_spec.rb
CHANGED
@@ -214,6 +214,10 @@ end
|
|
214
214
|
|
215
215
|
describe Hoodoo::Client do
|
216
216
|
|
217
|
+
before :each do
|
218
|
+
spec_helper_use_mock_memcached()
|
219
|
+
end
|
220
|
+
|
217
221
|
before :all do
|
218
222
|
@old_test_session = Hoodoo::Services::Middleware.test_session()
|
219
223
|
@port = spec_helper_start_svc_app_in_thread_for( RSpecClientTestService )
|
@@ -304,6 +304,8 @@ end
|
|
304
304
|
describe Hoodoo::Services::Middleware do
|
305
305
|
|
306
306
|
before :each do
|
307
|
+
spec_helper_use_mock_memcached()
|
308
|
+
|
307
309
|
@session_id = Hoodoo::UUID.generate
|
308
310
|
@caller_id = Hoodoo::UUID.generate
|
309
311
|
@caller_version = 1
|
@@ -343,14 +345,8 @@ describe Hoodoo::Services::Middleware do
|
|
343
345
|
Hoodoo::Services::Permissions::ALLOW
|
344
346
|
)
|
345
347
|
|
346
|
-
|
347
|
-
|
348
|
-
result = @session.save_to_memcached
|
349
|
-
raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
|
350
|
-
end
|
351
|
-
|
352
|
-
after :each do
|
353
|
-
Hoodoo::TransientStore::Mocks::DalliClient.reset()
|
348
|
+
result = @session.save_to_store
|
349
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
354
350
|
end
|
355
351
|
|
356
352
|
############################################################################
|
@@ -398,8 +394,8 @@ describe Hoodoo::Services::Middleware do
|
|
398
394
|
Hoodoo::Services::Permissions::ALLOW
|
399
395
|
)
|
400
396
|
|
401
|
-
result = @session.
|
402
|
-
raise "Can't save to mock
|
397
|
+
result = @session.save_to_store
|
398
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
403
399
|
|
404
400
|
expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
|
405
401
|
expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
|
@@ -432,8 +428,8 @@ describe Hoodoo::Services::Middleware do
|
|
432
428
|
Hoodoo::Services::Permissions::ALLOW
|
433
429
|
)
|
434
430
|
|
435
|
-
result = @session.
|
436
|
-
raise "Can't save to mock
|
431
|
+
result = @session.save_to_store
|
432
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
437
433
|
|
438
434
|
expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
|
439
435
|
expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
|
@@ -488,8 +484,8 @@ describe Hoodoo::Services::Middleware do
|
|
488
484
|
Hoodoo::Services::Permissions::ALLOW
|
489
485
|
)
|
490
486
|
|
491
|
-
result = @session.
|
492
|
-
raise "Can't save to mock
|
487
|
+
result = @session.save_to_store
|
488
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
493
489
|
|
494
490
|
expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
|
495
491
|
expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
|
@@ -578,8 +574,8 @@ describe Hoodoo::Services::Middleware do
|
|
578
574
|
Hoodoo::Services::Permissions::ALLOW
|
579
575
|
)
|
580
576
|
|
581
|
-
result = @session.
|
582
|
-
raise "Can't save to mock
|
577
|
+
result = @session.save_to_store
|
578
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
583
579
|
|
584
580
|
expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :list ).once.and_call_original
|
585
581
|
expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
|
@@ -646,7 +642,7 @@ describe Hoodoo::Services::Middleware do
|
|
646
642
|
#
|
647
643
|
it 'can deal with inter-resource session errors (2)' do
|
648
644
|
expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
|
649
|
-
expect_any_instance_of(Hoodoo::Services::Session).to receive( :
|
645
|
+
expect_any_instance_of(Hoodoo::Services::Session).to receive( :save_to_store ).once.and_return( :outdated )
|
650
646
|
expect_any_instance_of(RSpecAddPermTestDateImplementation).to_not receive( :show )
|
651
647
|
|
652
648
|
get '/v1/rspec_add_perm_test_clocks/any',
|
@@ -663,7 +659,7 @@ describe Hoodoo::Services::Middleware do
|
|
663
659
|
#
|
664
660
|
it 'can deal with inter-resource session errors (3)' do
|
665
661
|
expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
|
666
|
-
expect_any_instance_of(Hoodoo::Services::Session).to receive( :
|
662
|
+
expect_any_instance_of(Hoodoo::Services::Session).to receive( :save_to_store ).once.and_return( :fail )
|
667
663
|
expect_any_instance_of(RSpecAddPermTestDateImplementation).to_not receive( :show )
|
668
664
|
|
669
665
|
get '/v1/rspec_add_perm_test_clocks/any',
|
@@ -683,8 +679,8 @@ describe Hoodoo::Services::Middleware do
|
|
683
679
|
it 'handles nil permissions' do
|
684
680
|
@session.permissions = nil
|
685
681
|
|
686
|
-
result = @session.
|
687
|
-
raise "Can't save to mock
|
682
|
+
result = @session.save_to_store
|
683
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
688
684
|
|
689
685
|
expect_any_instance_of(RSpecAddPermTestClockImplementation).to_not receive( :show )
|
690
686
|
|
@@ -701,8 +697,8 @@ describe Hoodoo::Services::Middleware do
|
|
701
697
|
it 'handles empty permissions' do
|
702
698
|
@session.permissions = Hoodoo::Services::Permissions.new( {} )
|
703
699
|
|
704
|
-
result = @session.
|
705
|
-
raise "Can't save to mock
|
700
|
+
result = @session.save_to_store
|
701
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
706
702
|
|
707
703
|
expect_any_instance_of(RSpecAddPermTestClockImplementation).to_not receive( :show )
|
708
704
|
|
@@ -719,8 +715,8 @@ describe Hoodoo::Services::Middleware do
|
|
719
715
|
it 'handles default #verify response as deny' do
|
720
716
|
@session.permissions.set_resource( :RSpecAddPermTestClock, :show, Hoodoo::Services::Permissions::ASK )
|
721
717
|
|
722
|
-
result = @session.
|
723
|
-
raise "Can't save to mock
|
718
|
+
result = @session.save_to_store
|
719
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
724
720
|
|
725
721
|
expect_any_instance_of(Hoodoo::Services::Implementation).to receive( :verify ).once.and_call_original
|
726
722
|
expect_any_instance_of(RSpecAddPermTestClockImplementation).to_not receive( :show ).once.and_call_original
|
@@ -802,8 +798,8 @@ describe Hoodoo::Services::Middleware do
|
|
802
798
|
Hoodoo::Services::Permissions::ALLOW
|
803
799
|
)
|
804
800
|
|
805
|
-
result = @session.
|
806
|
-
raise "Can't save to mock
|
801
|
+
result = @session.save_to_store
|
802
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
807
803
|
|
808
804
|
expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
|
809
805
|
expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
|
@@ -834,8 +830,8 @@ describe Hoodoo::Services::Middleware do
|
|
834
830
|
Hoodoo::Services::Permissions::ALLOW
|
835
831
|
)
|
836
832
|
|
837
|
-
result = @session.
|
838
|
-
raise "Can't save to mock
|
833
|
+
result = @session.save_to_store
|
834
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
839
835
|
|
840
836
|
expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
|
841
837
|
expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
|
@@ -879,8 +875,8 @@ describe Hoodoo::Services::Middleware do
|
|
879
875
|
Hoodoo::Services::Permissions::ALLOW
|
880
876
|
)
|
881
877
|
|
882
|
-
result = @session.
|
883
|
-
raise "Can't save to mock
|
878
|
+
result = @session.save_to_store
|
879
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
884
880
|
|
885
881
|
expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
|
886
882
|
expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
|
@@ -954,8 +950,8 @@ describe Hoodoo::Services::Middleware do
|
|
954
950
|
Hoodoo::Services::Permissions::ALLOW
|
955
951
|
)
|
956
952
|
|
957
|
-
result = @session.
|
958
|
-
raise "Can't save to mock
|
953
|
+
result = @session.save_to_store
|
954
|
+
raise "Can't save to mock session store (result = #{result})" unless result == :ok
|
959
955
|
|
960
956
|
expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :list ).once.and_call_original
|
961
957
|
expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
|
@@ -1,459 +1,591 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'hoodoo/transient_store/mocks/dalli_client'
|
2
3
|
|
3
4
|
describe Hoodoo::Services::Session do
|
4
5
|
|
5
6
|
before :each do
|
6
|
-
|
7
|
+
spec_helper_use_mock_memcached()
|
7
8
|
end
|
8
9
|
|
9
|
-
|
10
|
-
expect( Hoodoo::Services::Session::MockDalliClient == Hoodoo::TransientStore::Mocks::DalliClient ).to eql( true )
|
11
|
-
expect {
|
12
|
-
Hoodoo::TransientStore::Mocks::DalliClient.reset()
|
13
|
-
}.to_not raise_error
|
14
|
-
end
|
10
|
+
# ==========================================================================
|
15
11
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
12
|
+
context 'basics' do
|
13
|
+
it 'initialises with default options' do
|
14
|
+
s = described_class.new()
|
15
|
+
expect( s.created_at ).to be_a( Time )
|
16
|
+
expect( Hoodoo::UUID.valid?( s.session_id ) ).to eq( true )
|
17
|
+
expect( s.memcached_host ).to be_nil
|
18
|
+
expect( s.caller_id ).to be_nil
|
19
|
+
expect( s.caller_version ).to eq( 0 )
|
20
|
+
end
|
24
21
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
22
|
+
it 'initialises with given options' do
|
23
|
+
s = described_class.new(
|
24
|
+
:session_id => '1234',
|
25
|
+
:memcached_host => 'abcd',
|
26
|
+
:caller_id => '0987',
|
27
|
+
:caller_version => 2
|
28
|
+
)
|
29
|
+
expect( s.created_at ).to be_a( Time )
|
30
|
+
expect( s.session_id ).to eq( '1234' )
|
31
|
+
expect( s.memcached_host ).to eq( 'abcd' )
|
32
|
+
expect( s.caller_id ).to eq( '0987' )
|
33
|
+
expect( s.caller_version ).to eq( 2 )
|
34
|
+
end
|
38
35
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
it 'reports not expired when it has no expiry' do
|
37
|
+
s = described_class.new
|
38
|
+
expect( s.expired? ).to eq( false )
|
39
|
+
end
|
43
40
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
41
|
+
it 'knows if expired' do
|
42
|
+
s = described_class.new
|
43
|
+
s.instance_variable_set( '@expires_at', Time.now - 1 )
|
44
|
+
expect( s.expired? ).to eq( true )
|
45
|
+
end
|
49
46
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
47
|
+
it 'converts to a Hash' do
|
48
|
+
s = described_class.new(
|
49
|
+
:session_id => '1234',
|
50
|
+
:memcached_host => 'abcd',
|
51
|
+
:caller_id => '0987',
|
52
|
+
:caller_version => 2
|
53
|
+
)
|
54
|
+
p = Hoodoo::Services::Permissions.new
|
58
55
|
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
s.permissions = p
|
57
|
+
s.identity = { 'foo' => 'foo', 'bar' => 'bar' }
|
58
|
+
s.scoping = { 'baz' => [ 'foo', 'bar', 'baz' ] }
|
62
59
|
|
63
|
-
|
60
|
+
h = s.to_h
|
64
61
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
62
|
+
expect( h ).to eq( {
|
63
|
+
'session_id' => '1234',
|
64
|
+
'caller_id' => '0987',
|
65
|
+
'caller_version' => 2,
|
69
66
|
|
70
|
-
|
67
|
+
'created_at' => s.created_at.iso8601,
|
71
68
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
69
|
+
'identity' => { 'foo' => 'foo', 'bar' => 'bar' },
|
70
|
+
'scoping' => { 'baz' => [ 'foo', 'bar', 'baz' ] },
|
71
|
+
'permissions' => p.to_h()
|
72
|
+
} )
|
73
|
+
end
|
77
74
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
75
|
+
it 'reads from a Hash' do
|
76
|
+
s = described_class.new
|
77
|
+
p = Hoodoo::Services::Permissions.new
|
78
|
+
c = Time.now.utc
|
79
|
+
e = Time.now.utc + 10
|
80
|
+
h = {
|
81
|
+
'session_id' => '1234',
|
82
|
+
'caller_id' => '0987',
|
83
|
+
'caller_version' => 2,
|
84
|
+
|
85
|
+
'created_at' => c.iso8601,
|
86
|
+
'expires_at' => e.iso8601,
|
87
|
+
|
88
|
+
'identity' => { 'foo' => 'foo', 'bar' => 'bar' },
|
89
|
+
'scoping' => { 'baz' => [ 'foo', 'bar', 'baz' ] },
|
90
|
+
'permissions' => p.to_h()
|
91
|
+
}
|
92
|
+
|
93
|
+
s.from_h!( h )
|
94
|
+
|
95
|
+
expect( s.session_id ).to eq( '1234' )
|
96
|
+
expect( s.caller_id ).to eq( '0987' )
|
97
|
+
expect( s.caller_version ).to eq( 2 )
|
98
|
+
expect( s.created_at ).to eq( Time.parse( c.iso8601 ) )
|
99
|
+
expect( s.expires_at ).to eq( Time.parse( e.iso8601 ) )
|
100
|
+
expect( s.identity.foo ).to eq( 'foo' )
|
101
|
+
expect( s.identity.bar ).to eq( 'bar' )
|
102
|
+
expect( s.scoping.baz ).to eq( [ 'foo', 'bar', 'baz' ] )
|
103
|
+
expect( s.permissions.to_h ).to eq( p.to_h )
|
104
|
+
end
|
108
105
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
106
|
+
it 'saves/loads to/from Memcached' do
|
107
|
+
s1 = described_class.new(
|
108
|
+
:session_id => '1234',
|
109
|
+
:memcached_host => 'abcd',
|
110
|
+
:caller_id => '0987',
|
111
|
+
:caller_version => 2
|
112
|
+
)
|
113
|
+
|
114
|
+
expect( s1.save_to_store ).to eq( :ok )
|
115
|
+
|
116
|
+
store = Hoodoo::TransientStore::Mocks::DalliClient.store()
|
117
|
+
expect( store[ '1234' ] ).to_not be_nil
|
118
|
+
expect( store[ '0987' ] ).to include( { :value => { 'version' => 2 } } )
|
119
|
+
expect( store[ '0987' ] ).to have_key( :expires_at )
|
120
|
+
expect( store[ '0987' ][ :expires_at ] ).to be_a( Time )
|
121
|
+
|
122
|
+
# Check that session gains an expiry time when saved.
|
123
|
+
#
|
124
|
+
expect( s1.expires_at ).to be_a( Time )
|
125
|
+
|
126
|
+
# Ensure "created_at" is significantly different in the next session.
|
127
|
+
# This is important to reliably detect session load failures in testing
|
128
|
+
# given "#iso8601()" time resolution limits and so-on.
|
129
|
+
#
|
130
|
+
sleep( 0.2 )
|
131
|
+
|
132
|
+
s2 = described_class.new
|
133
|
+
expect( s2.load_from_store!( s1.session_id ) ).to eq( :ok )
|
134
|
+
|
135
|
+
expect( s2.created_at ).to eq( Time.parse( s1.created_at.iso8601 ) )
|
136
|
+
expect( s2.expires_at ).to eq( Time.parse( s1.expires_at.iso8601 ) )
|
137
|
+
expect( s2.session_id ).to eq( s1.session_id )
|
138
|
+
expect( s2.memcached_host ).to be_nil
|
139
|
+
expect( s2.caller_id ).to eq( s1.caller_id )
|
140
|
+
expect( s2.caller_version ).to eq( s1.caller_version )
|
141
|
+
end
|
143
142
|
|
144
|
-
|
145
|
-
|
143
|
+
it 'can be deleted' do
|
144
|
+
s = described_class.new(
|
145
|
+
:session_id => '1234',
|
146
|
+
:memcached_host => 'abcd',
|
147
|
+
:caller_id => '0987',
|
148
|
+
:caller_version => 1
|
149
|
+
)
|
146
150
|
|
147
|
-
|
151
|
+
s.save_to_store
|
148
152
|
|
149
|
-
|
150
|
-
|
151
|
-
:memcached_host => 'abcd',
|
152
|
-
:caller_id => '0987',
|
153
|
-
:caller_version => 4
|
154
|
-
)
|
153
|
+
expect{ s.delete_from_store }.to change{ s.load_from_store!( s.session_id ) }.from( :ok ).to( :not_found )
|
154
|
+
end
|
155
155
|
|
156
|
-
|
156
|
+
it 'handles attempts to delete not-found things' do
|
157
|
+
s = described_class.new(
|
158
|
+
:session_id => '1234',
|
159
|
+
:memcached_host => 'abcd',
|
160
|
+
:caller_id => '0987',
|
161
|
+
:caller_version => 1
|
162
|
+
)
|
157
163
|
|
158
|
-
|
159
|
-
|
164
|
+
expect( s.delete_from_store ).to eq( :ok )
|
165
|
+
end
|
166
|
+
end
|
160
167
|
|
161
|
-
|
162
|
-
:session_id => '2345',
|
163
|
-
:memcached_host => 'abcd',
|
164
|
-
:caller_id => '0987',
|
165
|
-
:caller_version => 3
|
166
|
-
)
|
168
|
+
# ==========================================================================
|
167
169
|
|
168
|
-
|
169
|
-
|
170
|
+
context 'version manager' do
|
171
|
+
it 'refuses to save if a newer caller version is present' do
|
170
172
|
|
171
|
-
|
172
|
-
expect( described_class ).to receive( :connect_to_memcached ).exactly( 4 ).times.and_return( Hoodoo::TransientStore::Mocks::DalliClient.new )
|
173
|
-
loader = described_class.new
|
173
|
+
# Save a session with a high caller version
|
174
174
|
|
175
|
-
|
175
|
+
s1 = described_class.new(
|
176
|
+
:session_id => '1234',
|
177
|
+
:memcached_host => 'abcd',
|
178
|
+
:caller_id => '0987',
|
179
|
+
:caller_version => 4
|
180
|
+
)
|
176
181
|
|
177
|
-
|
178
|
-
:session_id => '1234',
|
179
|
-
:memcached_host => 'abcd',
|
180
|
-
:caller_id => '0987',
|
181
|
-
:caller_version => 1
|
182
|
-
)
|
182
|
+
expect( s1.save_to_store ).to eq( :ok )
|
183
183
|
|
184
|
-
|
184
|
+
# Save another with, initially, a lower caller version. The idea here
|
185
|
+
# is that session creation is underway when a caller gets updated.
|
185
186
|
|
186
|
-
|
187
|
+
s2 = described_class.new(
|
188
|
+
:session_id => '2345',
|
189
|
+
:memcached_host => 'abcd',
|
190
|
+
:caller_id => '0987',
|
191
|
+
:caller_version => 3
|
192
|
+
)
|
187
193
|
|
188
|
-
|
189
|
-
|
190
|
-
:memcached_host => 'abcd',
|
191
|
-
:caller_id => '0987',
|
192
|
-
:caller_version => 2
|
193
|
-
)
|
194
|
+
expect( s2.save_to_store ).to eq( :outdated )
|
195
|
+
end
|
194
196
|
|
195
|
-
|
197
|
+
it 'invalidates a session if the caller version advances during its lifetime' do
|
198
|
+
loader = described_class.new
|
196
199
|
|
197
|
-
|
200
|
+
# Save a session with a low caller version.
|
198
201
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
+
s1 = described_class.new(
|
203
|
+
:session_id => '1234',
|
204
|
+
:memcached_host => 'abcd',
|
205
|
+
:caller_id => '0987',
|
206
|
+
:caller_version => 1
|
207
|
+
)
|
202
208
|
|
203
|
-
|
204
|
-
expect( described_class ).to receive( :connect_to_memcached ).exactly( 5 ).times.and_return( Hoodoo::TransientStore::Mocks::DalliClient.new )
|
205
|
-
loader = described_class.new
|
209
|
+
expect( s1.save_to_store ).to eq( :ok )
|
206
210
|
|
207
|
-
|
211
|
+
# Save another with a higher caller version.
|
208
212
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
213
|
+
s2 = described_class.new(
|
214
|
+
:session_id => '2345',
|
215
|
+
:memcached_host => 'abcd',
|
216
|
+
:caller_id => '0987',
|
217
|
+
:caller_version => 2
|
218
|
+
)
|
215
219
|
|
216
|
-
|
220
|
+
expect( s2.save_to_store ).to eq( :ok )
|
217
221
|
|
218
|
-
|
222
|
+
# Should not be able to load the first one anymore.
|
219
223
|
|
220
|
-
|
224
|
+
expect( loader.load_from_store!( '1234' ) ).to eq( :outdated )
|
225
|
+
expect( loader.load_from_store!( '2345' ) ).to eq( :ok )
|
226
|
+
end
|
221
227
|
|
222
|
-
|
228
|
+
it 'refuses to load session if the caller version is outdated' do
|
229
|
+
loader = described_class.new
|
223
230
|
|
224
|
-
|
225
|
-
:session_id => '2345',
|
226
|
-
:memcached_host => 'abcd',
|
227
|
-
:caller_id => '0987',
|
228
|
-
:caller_version => 2
|
229
|
-
)
|
231
|
+
# Save a session with a low caller version
|
230
232
|
|
231
|
-
|
233
|
+
s1 = described_class.new(
|
234
|
+
:session_id => '1234',
|
235
|
+
:memcached_host => 'abcd',
|
236
|
+
:caller_id => '0987',
|
237
|
+
:caller_version => 1
|
238
|
+
)
|
232
239
|
|
233
|
-
|
240
|
+
expect( s1.save_to_store ).to eq( :ok )
|
234
241
|
|
235
|
-
|
242
|
+
# Should be able to load it back.
|
236
243
|
|
237
|
-
|
244
|
+
expect( loader.load_from_store!( '1234' ) ).to eq( :ok )
|
238
245
|
|
239
|
-
|
240
|
-
end
|
246
|
+
# Save another with a higher caller version.
|
241
247
|
|
242
|
-
|
243
|
-
|
244
|
-
|
248
|
+
s2 = described_class.new(
|
249
|
+
:session_id => '2345',
|
250
|
+
:memcached_host => 'abcd',
|
251
|
+
:caller_id => '0987',
|
252
|
+
:caller_version => 2
|
253
|
+
)
|
245
254
|
|
246
|
-
|
255
|
+
expect( s2.save_to_store ).to eq( :ok )
|
247
256
|
|
248
|
-
|
249
|
-
:session_id => '1234',
|
250
|
-
:memcached_host => 'abcd',
|
251
|
-
:caller_id => '0987',
|
252
|
-
:caller_version => 1
|
253
|
-
)
|
257
|
+
# Try to load the first one again; should fail.
|
254
258
|
|
255
|
-
|
256
|
-
h = obj.call( *args )
|
257
|
-
h[ 'expires_at' ] = ( Time.now - 1 ).utc.iso8601
|
258
|
-
h
|
259
|
-
end
|
259
|
+
expect( loader.load_from_store!( '1234' ) ).to eq( :outdated )
|
260
260
|
|
261
|
-
|
262
|
-
|
263
|
-
|
261
|
+
# The newer one should load OK.
|
262
|
+
|
263
|
+
expect( loader.load_from_store!( '2345' ) ).to eq( :ok )
|
264
|
+
end
|
264
265
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
266
|
+
it 'refuses to load session if the caller version is missing/expired' do
|
267
|
+
loader = described_class.new
|
268
|
+
|
269
|
+
# Save a session for caller ID '0987'.
|
270
|
+
#
|
271
|
+
s1 = described_class.new(
|
272
|
+
:session_id => '1234',
|
273
|
+
:memcached_host => 'abcd',
|
274
|
+
:caller_id => '0987',
|
275
|
+
:caller_version => 1
|
276
|
+
)
|
277
|
+
|
278
|
+
expect( s1.save_to_store ).to eq( :ok )
|
279
|
+
|
280
|
+
# Should be able to load it back.
|
281
|
+
#
|
282
|
+
expect( loader.load_from_store!( '1234' ) ).to eq( :ok )
|
283
|
+
|
284
|
+
# Manually wipe the caller version record, simulating expiry.
|
285
|
+
#
|
286
|
+
store = Hoodoo::TransientStore::Mocks::DalliClient.store()
|
287
|
+
store.delete( '0987' )
|
288
|
+
|
289
|
+
# Create a new session for some random other caller, reaffirming
|
290
|
+
# that we can still create new sessions for previously unrecorded
|
291
|
+
# caller IDs/versions.
|
292
|
+
|
293
|
+
s2 = described_class.new(
|
294
|
+
:session_id => '2345',
|
295
|
+
:memcached_host => 'abcd',
|
296
|
+
:caller_id => Hoodoo::UUID.generate(),
|
297
|
+
:caller_version => 1
|
298
|
+
)
|
299
|
+
|
300
|
+
expect( s2.save_to_store ).to eq( :ok )
|
301
|
+
|
302
|
+
# Try to load the first one again; should fail.
|
303
|
+
#
|
304
|
+
expect( loader.load_from_store!( '1234' ) ).to eq( :outdated )
|
305
|
+
|
306
|
+
# The newer one should load OK.
|
307
|
+
#
|
308
|
+
expect( loader.load_from_store!( '2345' ) ).to eq( :ok )
|
309
|
+
end
|
272
310
|
|
273
|
-
|
311
|
+
it 'refuses to load session if the session itself is expired' do
|
312
|
+
loader = described_class.new
|
274
313
|
|
275
|
-
|
276
|
-
expect( s.update_caller_version_in_memcached( 'abcd', 2, Hoodoo::TransientStore::Mocks::DalliClient.new ) ).to eq( :ok )
|
314
|
+
# Save a session with a high caller version
|
277
315
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
316
|
+
s = described_class.new(
|
317
|
+
:session_id => '1234',
|
318
|
+
:memcached_host => 'abcd',
|
319
|
+
:caller_id => '0987',
|
320
|
+
:caller_version => 1
|
321
|
+
)
|
282
322
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
323
|
+
expect( s ).to receive( :to_h ).and_wrap_original do | obj, args |
|
324
|
+
h = obj.call( *args )
|
325
|
+
h[ 'expires_at' ] = ( Time.now - 1 ).utc.iso8601
|
326
|
+
h
|
327
|
+
end
|
288
328
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
s.save_to_memcached()
|
293
|
-
}.to raise_error RuntimeError
|
329
|
+
expect( s.save_to_store ).to eq( :ok )
|
330
|
+
expect( loader.load_from_store!( '1234' ) ).to eq( :outdated )
|
331
|
+
end
|
294
332
|
end
|
295
333
|
|
296
|
-
|
297
|
-
loader = described_class.new
|
334
|
+
# ==========================================================================
|
298
335
|
|
299
|
-
|
300
|
-
|
336
|
+
context 'can explicitly update a caller' do
|
337
|
+
before :each do
|
338
|
+
@session = described_class.new(
|
339
|
+
:session_id => '1234',
|
340
|
+
:memcached_host => 'abcd',
|
341
|
+
:caller_id => '0987',
|
342
|
+
:caller_version => 1
|
343
|
+
)
|
301
344
|
end
|
302
345
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
)
|
346
|
+
after :each do
|
347
|
+
store = Hoodoo::TransientStore::Mocks::DalliClient.store()
|
348
|
+
expect( store[ '0987' ] ).to include( { :value => { 'version' => 23 } } )
|
349
|
+
expect( store[ 'efgh' ] ).to include( { :value => { 'version' => 3 } } )
|
350
|
+
end
|
309
351
|
|
310
|
-
|
311
|
-
|
352
|
+
it 'with modern interface and no caller-supplied client' do
|
353
|
+
expect( @session.update_caller_version_in_store( '0987', 23 ) ).to eq( :ok )
|
354
|
+
expect( @session.update_caller_version_in_store( 'efgh', 3 ) ).to eq( :ok )
|
355
|
+
end
|
312
356
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
357
|
+
it 'with modern interface and caller-supplied Hoodoo::TransientStore instance' do
|
358
|
+
local_store = Hoodoo::TransientStore.new(
|
359
|
+
storage_engine: :memcached,
|
360
|
+
storage_host_uri: 'abcd'
|
361
|
+
)
|
318
362
|
|
319
|
-
|
320
|
-
|
363
|
+
expect( @session.update_caller_version_in_store( '0987', 23, local_store ) ).to eq( :ok )
|
364
|
+
expect( @session.update_caller_version_in_store( 'efgh', 3, local_store ) ).to eq( :ok )
|
365
|
+
end
|
321
366
|
|
322
|
-
|
323
|
-
|
367
|
+
it 'with deprecated interface and no caller-supplied client' do
|
368
|
+
expect( @session.update_caller_version_in_memcached( '0987', 23 ) ).to eq( :ok )
|
369
|
+
expect( @session.update_caller_version_in_memcached( 'efgh', 3 ) ).to eq( :ok )
|
324
370
|
end
|
325
371
|
|
326
|
-
|
327
|
-
|
328
|
-
'Hoodoo::Services::Session\\#update_caller_version_in_memcached: Client version update - connection fault or corrupt record',
|
329
|
-
'Mock Memcached connection failure'
|
330
|
-
).and_call_original
|
331
|
-
)
|
372
|
+
it 'with deprecated interface and caller-supplied Dalli::Client instance' do
|
373
|
+
local_store = Hoodoo::TransientStore::Mocks::DalliClient.new
|
332
374
|
|
333
|
-
|
375
|
+
expect( @session.update_caller_version_in_memcached( '0987', 23, local_store ) ).to eq( :ok )
|
376
|
+
expect( @session.update_caller_version_in_memcached( 'efgh', 3, local_store ) ).to eq( :ok )
|
377
|
+
end
|
334
378
|
end
|
335
379
|
|
336
|
-
|
337
|
-
s = described_class.new(
|
338
|
-
:caller_id => '0987',
|
339
|
-
:caller_version => 1
|
340
|
-
)
|
380
|
+
# ==========================================================================
|
341
381
|
|
342
|
-
|
343
|
-
|
344
|
-
|
382
|
+
context 'error handling code' do
|
383
|
+
it 'handles invalid session IDs when loading' do
|
384
|
+
loader = described_class.new
|
385
|
+
expect( loader.load_from_store!( '1234' ) ).to eq( :not_found )
|
345
386
|
end
|
346
387
|
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
388
|
+
it 'complains if there is no caller ID' do
|
389
|
+
s = described_class.new
|
390
|
+
expect {
|
391
|
+
s.save_to_store()
|
392
|
+
}.to raise_error RuntimeError
|
393
|
+
end
|
353
394
|
|
354
|
-
|
355
|
-
|
395
|
+
it 'logs Memcached exceptions when loading' do
|
396
|
+
loader = described_class.new
|
356
397
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
:memcached_host => 'abcd',
|
361
|
-
:caller_id => '0987',
|
362
|
-
:caller_version => 1
|
363
|
-
)
|
398
|
+
expect_any_instance_of( Hoodoo::TransientStore::Mocks::DalliClient ).to receive( :get ).once do
|
399
|
+
raise 'Mock Memcached connection failure'
|
400
|
+
end
|
364
401
|
|
365
|
-
|
402
|
+
expect( Hoodoo::Services::Middleware.logger ).to(
|
403
|
+
receive( :warn ).once.with(
|
404
|
+
'Hoodoo::Services::Session\\#load_from_store!: Session loading failed - connection fault or session corrupt',
|
405
|
+
'Mock Memcached connection failure'
|
406
|
+
).and_call_original
|
407
|
+
)
|
366
408
|
|
367
|
-
|
368
|
-
|
409
|
+
expect( loader.load_from_store!( '1234' ) ).to eq( :fail )
|
410
|
+
end
|
369
411
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
:caller_version => 1
|
376
|
-
)
|
412
|
+
it 'logs Memcached exceptions when updating caller version during session saving' do
|
413
|
+
s = described_class.new(
|
414
|
+
:caller_id => '0987',
|
415
|
+
:caller_version => 1
|
416
|
+
)
|
377
417
|
|
378
|
-
|
379
|
-
|
418
|
+
# The first 'set' call is an attempt to update the caller version before
|
419
|
+
# the updated session is saved.
|
380
420
|
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
:session_id => '1234',
|
385
|
-
:memcached_host => 'abcd',
|
386
|
-
:caller_id => '0987',
|
387
|
-
:caller_version => 1
|
388
|
-
)
|
421
|
+
expect_any_instance_of( Hoodoo::TransientStore::Mocks::DalliClient ).to receive( :set ).once do
|
422
|
+
raise 'Mock Memcached connection failure'
|
423
|
+
end
|
389
424
|
|
390
|
-
|
425
|
+
expect( Hoodoo::Services::Middleware.logger ).to(
|
426
|
+
receive( :warn ).once.with(
|
427
|
+
'Hoodoo::Services::Session\\#update_caller_version_in_store: Client version update - connection fault or corrupt record',
|
428
|
+
'Mock Memcached connection failure'
|
429
|
+
).and_call_original
|
430
|
+
)
|
391
431
|
|
392
|
-
|
393
|
-
|
394
|
-
}
|
432
|
+
expect( s.save_to_store() ).to eq( :fail )
|
433
|
+
end
|
395
434
|
|
396
|
-
|
397
|
-
|
398
|
-
|
435
|
+
it 'logs Memcached exceptions when saving session' do
|
436
|
+
s = described_class.new(
|
437
|
+
:caller_id => '0987',
|
438
|
+
:caller_version => 1
|
439
|
+
)
|
399
440
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
before :example do
|
405
|
-
# Clear the connection cache for each test
|
406
|
-
Hoodoo::Services::Session.class_variable_set( '@@dalli_clients', nil ) # Hack for test!
|
407
|
-
Hoodoo::TransientStore::Mocks::DalliClient.bypass( true )
|
408
|
-
end
|
441
|
+
expect_any_instance_of( Hoodoo::TransientStore::Mocks::DalliClient ).to receive( :set ).once.and_call_original
|
442
|
+
expect_any_instance_of( Hoodoo::TransientStore::Mocks::DalliClient ).to receive( :set ).once do
|
443
|
+
raise 'Mock Memcached connection failure'
|
444
|
+
end
|
409
445
|
|
410
|
-
|
411
|
-
|
412
|
-
|
446
|
+
expect( Hoodoo::Services::Middleware.logger ).to(
|
447
|
+
receive( :warn ).once.with(
|
448
|
+
'Hoodoo::Services::Session\\#save_to_store: Session saving failed - connection fault or session corrupt',
|
449
|
+
'Mock Memcached connection failure'
|
450
|
+
).and_call_original
|
451
|
+
)
|
413
452
|
|
414
|
-
|
415
|
-
|
416
|
-
described_class.connect_to_memcached( nil )
|
417
|
-
}.to raise_error RuntimeError
|
453
|
+
expect( s.save_to_store() ).to eq( :fail )
|
454
|
+
end
|
418
455
|
|
419
|
-
|
420
|
-
|
421
|
-
|
456
|
+
it 'handles unknown Hoodoo::TransientStore engine failures' do
|
457
|
+
s = described_class.new(
|
458
|
+
:session_id => '1234',
|
459
|
+
:memcached_host => 'abcd',
|
460
|
+
:caller_id => '0987',
|
461
|
+
:caller_version => 1
|
462
|
+
)
|
463
|
+
|
464
|
+
s.save_to_store
|
465
|
+
allow_any_instance_of( Hoodoo::TransientStore ).to(
|
466
|
+
receive( :delete ).
|
467
|
+
and_return( false )
|
468
|
+
)
|
469
|
+
|
470
|
+
expect( Hoodoo::Services::Middleware.logger ).to receive( :warn )
|
471
|
+
expect( s.delete_from_store ).to eq( :fail )
|
422
472
|
end
|
423
473
|
|
424
|
-
it '
|
425
|
-
|
426
|
-
|
474
|
+
it 'handles unknown Hoodoo::TransientStore engine returned exceptions' do
|
475
|
+
s = described_class.new(
|
476
|
+
:session_id => '1234',
|
477
|
+
:memcached_host => 'abcd',
|
478
|
+
:caller_id => '0987',
|
479
|
+
:caller_version => 1
|
480
|
+
)
|
481
|
+
|
482
|
+
s.save_to_store
|
483
|
+
allow_any_instance_of( Hoodoo::TransientStore ).to(
|
484
|
+
receive( :delete ).
|
485
|
+
and_return( RuntimeError.new( 'Intentional exception' ) )
|
486
|
+
)
|
487
|
+
|
488
|
+
expect( Hoodoo::Services::Middleware.logger ).to receive( :warn )
|
489
|
+
expect( s.delete_from_store ).to eq( :fail )
|
427
490
|
end
|
428
491
|
|
429
|
-
it '
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
492
|
+
it 'logs and reports internal deletion exceptions' do
|
493
|
+
s = described_class.new(
|
494
|
+
:session_id => '1234',
|
495
|
+
:memcached_host => 'abcd',
|
496
|
+
:caller_id => '0987',
|
497
|
+
:caller_version => 1
|
498
|
+
)
|
499
|
+
|
500
|
+
s.save_to_store
|
501
|
+
|
502
|
+
allow_any_instance_of( described_class ).to(
|
503
|
+
receive( :get_store ).
|
504
|
+
and_raise( 'Intentional exception' )
|
505
|
+
)
|
506
|
+
|
507
|
+
expect( Hoodoo::Services::Middleware.logger ).to receive( :warn )
|
508
|
+
expect( s.delete_from_store ).to eq( :fail )
|
434
509
|
end
|
510
|
+
end
|
435
511
|
|
436
|
-
|
437
|
-
|
438
|
-
|
512
|
+
# ==========================================================================
|
513
|
+
|
514
|
+
context 'legacy' do
|
515
|
+
context 'Memcached-bound code' do
|
516
|
+
before :example do
|
517
|
+
|
518
|
+
# Clear the connection cache for each test
|
519
|
+
#
|
520
|
+
Hoodoo::Services::Session.class_variable_set( '@@stores', nil ) # Hack for test!
|
521
|
+
|
522
|
+
@instance = described_class.new(
|
523
|
+
:session_id => '1234',
|
524
|
+
:memcached_host => 'abcd',
|
525
|
+
:caller_id => '0987',
|
526
|
+
:caller_version => 1
|
527
|
+
)
|
439
528
|
end
|
440
529
|
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
530
|
+
it 'tries to connect' do
|
531
|
+
expect_any_instance_of( Hoodoo::TransientStore::Mocks::DalliClient ).to receive( :stats ).and_return( {} )
|
532
|
+
expect( @instance.send( :get_store ) ).to be_a( Hoodoo::TransientStore )
|
533
|
+
end
|
534
|
+
|
535
|
+
it 'handles connection failures' do
|
536
|
+
expect_any_instance_of( Hoodoo::TransientStore::Mocks::DalliClient ).to receive( :stats ).and_return( nil )
|
537
|
+
expect {
|
538
|
+
@instance.send( :get_store )
|
539
|
+
}.to raise_error RuntimeError
|
540
|
+
end
|
541
|
+
|
542
|
+
it 'handles connection exceptions' do
|
543
|
+
expect_any_instance_of( Hoodoo::TransientStore ).to receive( :initialize ) do
|
544
|
+
raise 'Mock TransientStore constructor failure'
|
545
|
+
end
|
546
|
+
|
547
|
+
expect {
|
548
|
+
@instance.send( :get_store )
|
549
|
+
}.to raise_error RuntimeError
|
550
|
+
end
|
551
|
+
|
552
|
+
it 'only initialises once for one given host' do
|
553
|
+
expect( Hoodoo::TransientStore::Memcached ).to receive( :new ).once.and_call_original()
|
554
|
+
|
555
|
+
@instance.memcached_host = 'one'
|
556
|
+
1.upto( 3 ) do
|
557
|
+
@instance.send( :get_store )
|
558
|
+
end
|
445
559
|
|
446
|
-
|
447
|
-
expect( Dalli::Client ).to receive( :new ).once.and_return( Hoodoo::TransientStore::Mocks::DalliClient.new )
|
560
|
+
expect( Hoodoo::TransientStore::Memcached ).to receive( :new ).once.and_call_original()
|
448
561
|
|
449
|
-
|
450
|
-
|
562
|
+
@instance.memcached_host = 'two'
|
563
|
+
1.upto( 3 ) do
|
564
|
+
@instance.send( :get_store )
|
565
|
+
end
|
451
566
|
end
|
567
|
+
end
|
452
568
|
|
453
|
-
|
569
|
+
context 'compatibility' do
|
570
|
+
it 'via alias to the TransientStore mock back-end' do
|
571
|
+
expect( Hoodoo::Services::Session::MockDalliClient == Hoodoo::TransientStore::Mocks::DalliClient ).to eql( true )
|
572
|
+
expect {
|
573
|
+
Hoodoo::TransientStore::Mocks::DalliClient.reset()
|
574
|
+
}.to_not raise_error
|
575
|
+
end
|
454
576
|
|
455
|
-
|
456
|
-
described_class.
|
577
|
+
it 'via aliases for deprecated methods' do
|
578
|
+
s = described_class.new(
|
579
|
+
:session_id => '1234',
|
580
|
+
:memcached_host => 'abcd',
|
581
|
+
:caller_id => '0987',
|
582
|
+
:caller_version => 2
|
583
|
+
)
|
584
|
+
|
585
|
+
expect( s ).to respond_to( :save_to_memcached )
|
586
|
+
expect( s ).to respond_to( :load_from_memcached! )
|
587
|
+
expect( s ).to respond_to( :update_caller_version_in_memcached )
|
588
|
+
expect( s ).to respond_to( :delete_from_memcached )
|
457
589
|
end
|
458
590
|
end
|
459
591
|
end
|